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

PostgreSQL — skorelowane podzapytanie nie powiodło się?

Kilka ważnych punktów dotyczących używania SQL:

  • Nie możesz używać aliasów kolumn w klauzuli WHERE, ale możesz w klauzuli HAVING. To jest przyczyna otrzymanego błędu.
  • Możesz lepiej liczyć, używając funkcji JOIN i GROUP BY niż za pomocą skorelowanych podzapytań. Będzie znacznie szybciej.
  • Użyj klauzuli HAVING do filtrowania grup.

Oto sposób, w jaki napisałbym to zapytanie:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Zdaję sobie sprawę, że to zapytanie może pominąć JOIN z t1, jak w rozwiązaniu Charlesa Bretany. Ale zakładam, że możesz chcieć, aby zapytanie zawierało inne kolumny z t1.

Re:pytanie w komentarzu:

Różnica polega na tym, że WHERE klauzula jest oceniana w wierszach, przed GROUP BY redukuje grupy do jednego wiersza na grupę. HAVING klauzula jest oceniana po utworzeniu grup. Nie możesz więc na przykład zmienić COUNT() grupy za pomocą HAVING; możesz wykluczyć tylko samą grupę.

SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

W powyższym zapytaniu WHERE filtry dla wierszy pasujących do warunku i HAVING filtry dla grup, które mają co najmniej pięć liczników.

Punktem, który powoduje zamieszanie u większości ludzi, jest to, że nie mają GROUP BY klauzula, więc wydaje się jak HAVING i WHERE są wymienne.

WHERE jest oceniany przed wyrażeniami na liście wyboru. Może to nie być oczywiste, ponieważ składnia SQL umieszcza listę wyboru na pierwszym miejscu. Możesz więc zaoszczędzić wiele kosztownych obliczeń, używając WHERE aby ograniczyć wiersze.

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Jeśli używasz zapytania takiego jak powyżej, wyrażenia na liście wyboru są obliczane dla każdego wiersza , tylko po to, aby odrzucić większość wyników z powodu HAVING stan. Jednak poniższe zapytanie oblicza wyrażenie tylko dla pojedynczego wiersza pasujące do WHERE stan.

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

Podsumowując, zapytania są uruchamiane przez silnik bazy danych zgodnie z serią kroków:

  1. Wygeneruj zestaw wierszy z tabel, w tym wiersze utworzone przez JOIN .
  2. Oceń WHERE warunki względem zestawu wierszy, odfiltrowując wiersze, które nie pasują.
  3. Oblicz wyrażenia na liście wyboru dla każdego w zestawie wierszy.
  4. Zastosuj aliasy kolumn (pamiętaj, że jest to osobny krok, co oznacza, że ​​nie możesz używać aliasów w wyrażeniach na liście wyboru).
  5. Skondensuj grupy w jednym wierszu na grupę, zgodnie z GROUP BY klauzula.
  6. Oceń HAVING warunki przeciwko grupom, odfiltrowując grupy, które nie pasują.
  7. Sortuj wyniki według ORDER BY klauzula.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd składni w kodzie testowym UPSERT

  2. Wydajne zapytanie o najnowsze rekordy za pomocą Postgresql

  3. Tabela łączenia sql z zapytaniem dotyczącym aktywnego rekordu szyn

  4. Zoptymalizuj zakres zapytań sygnatury czasowej Postgres

  5. Problem z przywracaniem bazy danych Heroku