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

Kueri dengan LEFT JOIN tidak mengembalikan baris untuk hitungan 0

Perbaiki LEFT JOIN

Ini akan berhasil:

SELECT o.name AS organisation_name, count(e.id) AS total_used
FROM   organisations   o
LEFT   JOIN exam_items e ON e.organisation_id = o.id 
                        AND e.item_template_id = #{sanitize(item_template_id)}
                        AND e.used
GROUP  BY o.name
ORDER  BY o.name;

Anda memiliki LEFT [OUTER] JOIN tapi nanti WHERE kondisi membuatnya bertindak seperti [INNER] JOIN biasa .
Pindahkan kondisi ke JOIN klausa untuk membuatnya bekerja sebagaimana dimaksud. Dengan cara ini, hanya baris yang memenuhi semua kondisi ini yang akan digabungkan (atau kolom dari kanan tabel diisi dengan NULL). Seperti yang Anda alami, baris yang digabungkan diuji untuk kondisi tambahan secara virtual setelah LEFT JOIN dan dihapus jika tidak lulus, seperti dengan JOIN plain biasa .

count() tidak pernah mengembalikan NULL untuk memulai. Ini pengecualian di antara fungsi agregat dalam hal ini. Oleh karena itu, COALESCE(COUNT(col)) tidak pernah masuk akal, bahkan dengan parameter tambahan. Panduan:

Perlu diperhatikan bahwa kecuali count , fungsi-fungsi ini mengembalikan nilai nol saat tidak ada baris yang dipilih.

Penekanan saya yang berani. Lihat:

  • Hitung jumlah atribut yang NULL untuk satu baris

count() harus pada kolom yang ditentukan NOT NULL (seperti e.id ), atau di mana kondisi join menjamin NOT NULL (e.organisation_id , e.item_template_id , atau e.used ) dalam contoh.

Sejak used adalah ketik boolean , ekspresi e.used = true adalah kebisingan yang membakar hanya e.used .

Sejak o.name tidak didefinisikan UNIQUE NOT NULL , Anda mungkin ingin GROUP BY o.id sebagai gantinya (id menjadi PK) - kecuali jika Anda berniat untuk melipat baris dengan nama yang sama (termasuk NULL).

Agregat dulu, gabung nanti

Jika sebagian besar atau semua baris exam_items dihitung dalam proses, kueri yang setara ini biasanya jauh lebih cepat/lebih murah:

SELECT o.id, o.name AS organisation_name, e.total_used
FROM   organisations o
LEFT   JOIN (
   SELECT organisation_id AS id   -- alias to simplify join syntax
        , count(*) AS total_used  -- count(*) = fastest to count all
   FROM   exam_items
   WHERE  item_template_id = #{sanitize(item_template_id)}
   AND    used
   GROUP  BY 1
   ) e USING (id)
ORDER  BY o.name, o.id;

(Ini dengan asumsi bahwa Anda tidak ingin melipat baris dengan nama yang sama seperti yang disebutkan di atas - kasus biasa.)

Sekarang kita dapat menggunakan count(*) yang lebih cepat / lebih sederhana di subquery, dan kita tidak memerlukan GROUP BY di bagian luar SELECT .

Lihat:

  • Beberapa panggilan array_agg() dalam satu kueri


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana Acos() Bekerja di PostgreSQL

  2. Barman Cloud – Bagian 2:Cloud Backup

  3. gabungkan dua tabel berbeda dan hapus entri yang digandakan

  4. Optimasi Kueri di PostgreSQL. JELASKAN Dasar-dasar – Bagian 1

  5. Dapatkan Abad dari Tanggal di PostgreSQL