PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách tốt hơn nhiều câu lệnh SELECT?

Bạn có thể nhóm hầu hết chi phí trong một truy vấn chính trong CTE và sử dụng lại kết quả nhiều lần.
Điều này trả về một hàng đơn có ba cột được đặt tên theo mỗi loại type ( theo yêu cầu trong nhận xét ):

WITH cte AS (
   SELECT cai.id, cai.activity_id, cas.key, cas.value
   FROM   common_activityinstance cai
   JOIN   common_activityinstance_settings s ON s.activityinstance_id = cai.id
   JOIN   common_activitysetting cas ON cas.id = s.id
   WHERE  cai.end_time::date = '2015-09-12'   -- problem?
   AND    cai.activity_type = 'QZ'
   AND   (cas.key = 'disable_student_nav' AND cas.value IN ('True', 'False') OR
          cas.key = 'pacing' AND cas.value IN ('student', 'teacher'))
   )
SELECT *
FROM  (
   SELECT count(*) AS spf
   FROM  (
      SELECT c.id
      FROM   cte c
      JOIN   quizzes_quiz q ON q.id = c.activity_id
      WHERE  q.name <> 'Exit Ticket Quiz'
      AND   (c.key, c.value) IN (('disable_student_nav', 'True')
                               , ('pacing', 'student'))
      GROUP  BY 1
      HAVING count(*) = 2
      ) sub
   ) spf
,  (
   SELECT count(key = 'disable_student_nav' AND value = 'False' OR NULL) AS spn
        , count(key = 'pacing' AND value = 'teacher' OR NULL) AS tp
   FROM   cte
   ) spn_tp;

Nên làm việc cho Postgres 9.3. Trong Postgres 9.4, bạn có thể sử dụng FILTER tổng hợp mới mệnh đề:

  count(*) FILTER (WHERE key = 'disable_student_nav' AND value = 'False') AS spn
, count(*) FILTER (WHERE key = 'pacing' AND value = 'teacher') AS tp

Chi tiết cho cả hai biến thể cú pháp:

Điều kiện được đánh dấu là problem? có thể là vấn đề lớn về hiệu suất, tùy thuộc vào loại dữ liệu của cai.end_time . Đối với một, nó không phải là sargable . Và nếu đó là timestamptz loại, biểu thức khó lập chỉ mục, vì kết quả phụ thuộc vào cài đặt múi giờ hiện tại của phiên - điều này cũng có thể dẫn đến kết quả khác nhau khi được thực thi ở các múi giờ khác nhau.

So sánh:

Bạn chỉ cần đặt tên cho múi giờ được cho là xác định ngày của bạn. Lấy múi giờ của tôi ở Vienna làm ví dụ:

WHERE  cai.end_time >= '2015-09-12 0:0'::timestamp AT TIME ZONE 'Europe/Vienna' 
AND    cai.end_time <  '2015-09-13 0:0'::timestamp AT TIME ZONE 'Europe/Vienna'

Bạn có thể cung cấp timestamptz đơn giản giá trị cũng vậy. Bạn thậm chí có thể chỉ:

WHERE  cai.end_time >= '2015-09-12'::date
AND    cai.end_time <  '2015-09-12'::date + 1

Nhưng biến thể đầu tiên không phụ thuộc vào cài đặt múi giờ hiện tại.
Giải thích chi tiết trong các liên kết ở trên.

Giờ đây, truy vấn có thể sử dụng chỉ mục của bạn và sẽ nhanh hơn nhiều nếu có nhiều ngày khác nhau trong bảng của bạn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Truy vấn postgres rất chậm với current_date ::date thay vì hardcoded date

  2. PostgreSQL có sử dụng tf-idf không?

  3. Postgres:Lỗi khi sử dụng GROUP BY và ORDER (trên heroku)

  4. Trình diễn SQL injection trong PL / pgSQL

  5. PostgreSQL 9.5:Ẩn mật khẩu khỏi kết nối dblink