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:
- Rút hai truy vấn từ cùng một bảng
- Trừ giờ kể từ bây giờ ( ) chức năng
- Bỏ qua hoàn toàn các múi giờ trong Rails và PostgreSQL
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.