PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zapytanie z LEFT JOIN nie zwraca wierszy dla liczby 0

Napraw LEFT JOIN

To powinno działać:

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;

Masz LEFT [OUTER] JOIN ale późniejszy WHERE warunki sprawiły, że zachowywał się jak zwykły [INNER] JOIN .
Przenieś warunki do JOIN klauzulę, aby działała zgodnie z przeznaczeniem. W ten sposób w pierwszej kolejności łączone są tylko wiersze, które spełniają wszystkie te warunki (lub kolumny od prawej tabele są wypełnione NULL). Tak jak wcześniej, połączone rzędy są testowane pod kątem dodatkowych warunków praktycznie po LEFT JOIN i usuwane, jeśli nie przejdą, tak jak w przypadku zwykłego JOIN .

count() na początku nigdy nie zwraca wartości NULL. Jest to wyjątek wśród funkcji agregujących pod tym względem. Dlatego COALESCE(COUNT(col)) nigdy ma sens, nawet przy dodatkowych parametrach. Instrukcja:

Należy zauważyć, że z wyjątkiem count , te funkcje zwracają wartość null, gdy nie zaznaczono żadnych wierszy.

Moje odważne podkreślenie. Zobacz:

  • Policz liczbę atrybutów, które mają wartość NULL dla wiersza

count() musi znajdować się w zdefiniowanej kolumnie NOT NULL (np. e.id ) lub gdzie warunek łączenia gwarantuje NOT NULL (e.organisation_id , e.item_template_id lub e.used ) w przykładzie.

Ponieważ used to typ boolean , wyrażenie e.used = true jest hałasem, który spala się tylko do e.used .

Od o.name nie jest zdefiniowany UNIQUE NOT NULL , możesz chcieć GROUP BY o.id zamiast tego (id będąc PK) - chyba że zamierzasz do składania wierszy o tej samej nazwie (w tym NULL).

Najpierw agreguj, dołącz później

Jeśli większość lub wszystkie wiersze exam_items są liczone w procesie, to równoważne zapytanie jest zazwyczaj znacznie szybsze / tańsze:

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;

(Przy założeniu, że nie chcesz składać wierszy o tej samej nazwie, jak wspomniana powyżej - typowy przypadek).

Teraz możemy użyć szybszego / prostszego count(*) w podzapytaniu i nie potrzebujemy GROUP BY w zewnętrznym SELECT .

Zobacz:

  • Wiele wywołań array_agg() w jednym zapytaniu


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oblicz Max of Sum pola z adnotacjami w pogrupowanym zapytaniu w Django ORM?

  2. Jaka jest różnica między `->>` a `->` w Postgres SQL?

  3. Zwróć zestaw rekordów (wirtualną tabelę) z funkcji

  4. PostgreSQL - Zmień nazwę bazy danych

  5. Liczba PostgreSQL ile razy podciąg występuje w tekście