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

Truy vấn với LEFT JOIN không trả về các hàng có số lượng là 0

Sửa lỗi LEFT JOIN

Điều này sẽ hoạt động:

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;

Bạn đã có LEFT [OUTER] JOIN nhưng WHERE muộn hơn các điều kiện khiến nó hoạt động giống như một [INNER] JOIN đơn giản .
Di chuyển (các) điều kiện đến JOIN để làm cho nó hoạt động như dự định. Bằng cách này, chỉ các hàng đáp ứng tất cả các điều kiện này mới được nối ở vị trí đầu tiên (hoặc các cột từ bên phải bảng được điền bằng NULL). Giống như bạn đã có, các hàng đã nối sẽ được kiểm tra các điều kiện bổ sung hầu như sau LEFT JOIN và bị xóa nếu chúng không đạt, giống như với JOIN đơn giản .

count() không bao giờ trả về NULL để bắt đầu với. Đó là một ngoại lệ trong số các hàm tổng hợp về mặt này. Do đó, COALESCE(COUNT(col)) không bao giờ có ý nghĩa, ngay cả với các tham số bổ sung. Hướng dẫn sử dụng:

Cần lưu ý rằng ngoại trừ count , các hàm này trả về giá trị null khi không có hàng nào được chọn.

Tôi nhấn mạnh đậm. Xem:

  • Đếm số thuộc tính là NULL cho một hàng

count() phải nằm trên một cột được xác định NOT NULL (như e.id ), hoặc nơi điều kiện tham gia đảm bảo NOT NULL (e.organisation_id , e.item_template_id hoặc e.used ) trong ví dụ.

Kể từ khi used là loại boolean , biểu thức e.used = true là tiếng ồn chỉ còn e.used .

Kể từ khi o.name không được xác định UNIQUE NOT NULL , bạn có thể muốn GROUP BY o.id thay vào đó (id là PK) - trừ khi bạn có ý định để gấp các hàng có cùng tên (bao gồm cả NULL).

Tổng hợp trước, tham gia sau

Nếu hầu hết hoặc tất cả các hàng của exam_items được tính trong quá trình này, truy vấn tương đương này thường nhanh hơn / rẻ hơn đáng kể:

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;

(Điều này giả sử rằng bạn không muốn gấp các hàng có cùng tên như đã đề cập ở trên - trường hợp điển hình.)

Giờ đây, chúng ta có thể sử dụng count(*) nhanh hơn / đơn giản hơn trong truy vấn con và chúng ta không cần GROUP BY trong SELECT bên ngoài .

Xem:

  • Nhiều lệnh gọi array_agg () trong một truy vấn duy nhất


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ánh xạ trường điểm hình học PostGIS với Hibernate trên Spring Boot

  2. Cột thả không xóa hoàn toàn các tham chiếu cột - postgresql

  3. Công bố repmgr 2.0

  4. Nối một chuỗi và một số trong PostgreSQL

  5. Thay đổi loại trường varchar thành số nguyên:không thể được truyền tự động thành loại số nguyên