sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL – selhání korelovaného dílčího dotazu?

Několik důležitých bodů o používání SQL:

  • Aliasy sloupců nelze použít v klauzuli WHERE, ale v klauzuli HAVING ano. To je příčina vaší chyby.
  • Počítání můžete provést lépe pomocí JOIN a GROUP BY než pomocí korelovaných poddotazů. Bude to mnohem rychlejší.
  • K filtrování skupin použijte klauzuli HAVING.

Tento dotaz bych napsal takto:

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

Uvědomuji si, že tento dotaz může přeskočit JOIN s t1, jako v řešení Charlese Bretany. Předpokládám však, že byste mohli chtít, aby dotaz zahrnoval některé další sloupce z t1.

Re:otázka v komentáři:

Rozdíl je v tom, že WHERE klauzule se vyhodnocuje na řádcích před GROUP BY redukuje skupiny na jeden řádek na skupinu. HAVING klauzule se hodnotí po vytvoření skupin. Nemůžete tedy například změnit COUNT() skupiny pomocí HAVING; můžete vyloučit pouze samotnou skupinu.

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;

Ve výše uvedeném dotazu WHERE filtry pro řádky odpovídající podmínce a HAVING filtry pro skupiny, které mají alespoň pět.

Bod, který většině lidí způsobuje zmatek, je, když nemají GROUP BY klauzule, tak se zdá jako HAVING a WHERE jsou zaměnitelné.

WHERE je vyhodnocen před výrazy ve výběrovém seznamu. To nemusí být zřejmé, protože syntaxe SQL klade výběrový seznam na první místo. Použitím WHERE si tedy můžete ušetřit spoustu drahých výpočtů pro omezení řádků.

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

Pokud použijete dotaz jako výše, výrazy ve výběrovém seznamu se vypočítají pro každý řádek , pouze zahodit většinu výsledků kvůli HAVING stav. Dotaz níže však vypočítá výraz pouze pro jeden řádek odpovídající WHERE podmínka.

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

Abychom to shrnuli, dotazy spouští databázový stroj podle série kroků:

  1. Generujte sadu řádků z tabulek, včetně všech řádků vytvořených JOIN .
  2. Vyhodnoťte WHERE podmínky vůči sadě řádků, odfiltrování řádků, které se neshodují.
  3. Vypočítejte výrazy ve výběrovém seznamu pro každý v sadě řádků.
  4. Použít aliasy sloupců (všimněte si, že se jedná o samostatný krok, což znamená, že nemůžete používat aliasy ve výrazech ve výběrovém seznamu).
  5. Zhustit skupiny na jeden řádek na skupinu podle GROUP BY doložka.
  6. Vyhodnoťte HAVING podmínky vůči skupinám, odfiltrování skupin, které se neshodují.
  7. Seřaďte výsledek podle ORDER BY doložka.


  1. Načítání výpisu v kódování UTF-8 do MySQL

  2. SQL a jedinečné kombinace n-sloupců

  3. převést časové razítko mysql na skutečné datum a čas?

  4. MySQL fulltextové vyhledávání slov se třemi nebo méně písmeny