PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara yang lebih baik daripada beberapa pernyataan SELECT?

Anda dapat menggabungkan sebagian besar biaya dalam satu kueri utama dalam CTE dan gunakan kembali hasilnya beberapa kali.
Ini mengembalikan baris tunggal dengan tiga kolom dinamai menurut setiap type (seperti yang diminta di komentar ):

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;

Harus bekerja untuk Postgres 9.3. Di Postgres 9.4 Anda dapat menggunakan FILTER agregat baru klausa:

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

Detail untuk kedua varian sintaks:

Kondisi ditandai problem? mungkin masalah kinerja yang besar, tergantung pada tipe data cai.end_time . Pertama, ini bukan sargable . Dan jika itu adalah timestamptz ketik, ekspresinya sulit untuk diindeks, karena hasilnya bergantung pada pengaturan zona waktu sesi saat ini - yang juga dapat menghasilkan hasil yang berbeda ketika dieksekusi di zona waktu yang berbeda.

Bandingkan:

Anda hanya perlu memberi nama zona waktu yang seharusnya menentukan tanggal Anda. Mengambil zona waktu saya di Wina sebagai contoh:

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'

Anda dapat memberikan timestamptz sederhana nilai-nilai juga. Anda bahkan bisa:

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

Namun varian pertama tidak bergantung pada pengaturan zona waktu saat ini.
Penjelasan detail pada link di atas.

Sekarang kueri dapat menggunakan indeks Anda dan akan jauh lebih cepat jika ada banyak hari berbeda di tabel Anda.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Permintaan lambat dengan gabungan luar kiri dan kondisi nol

  2. Cara Mengembalikan Hasil Kueri sebagai Daftar Dipisahkan Koma di PostgreSQL

  3. Bagaimana dan mengapa menambahkan kunci utama ke tabel database SQL saya ketika saya sudah memiliki indeks

  4. doktrin dbal querybuilder sebagai pernyataan yang disiapkan

  5. Apa yang disiratkan oleh kode berikut CREATE FUNCTION sebagai string?