SQL HAVING vs WHERE – Často se zde dělá chyba

SQL HAVING klauzule je speciálním druhem SQL příkazu, který se chová podobně jako jako WHERE. To znamená, že pomocí ní definujeme omezující podmínku při vyhledávání nebo manipulaci s tabulkami. Mezi oběma klauzulemi jsou ale významné rozdíly. Pojďmě si tedy SQL HAVING vs WHERE odlišnosti popsat.

Pořadí v SQL skriptu

  1. SELECT
  2. FROM
  3. WHERE
  4. GROUP BY
  5. HAVING
  6. ORDER BY

Proč existují 2 klauzule pro definování podmínek? Odpověď leží v článku logického zpracování dotazu. Tam vidíme, že pořadí zpracování skriptu je následující:

  1. FROM,
  2. WHERE,
  3. GROUP BY,
  4. HAVING,
  5. SELECT,
  6. ORDER BY

Dobře si prohlédněte pořadí zpracování. Z výše uvedeného plyne, že např. agregační operace (GROUP BY) je zpracována až po vyhodnocení podmínek ve WHERE klauzuli. Kam bychom napsali do SQL skriptu podmínku, která je založena na agregaci SUMA(něco)>0? Museli bychom podmínku vyhodnotit na dvakrát (přes vnořený dotaz, CTE a podobně). Naštěstí to není potřeba a můžeme pro podobné podmínky využít klauzuli HAVING.

Shrnutí:

  • Do WHERE píšeme podmínky, které pracují s tady v původní (nezagregované podobě).
  • Agregační podmínka se zadává do HAVING, protože když přijde tato klauzule v rámci vyhodnocení skriptu na řadu, je SUMA(něčeho) už spočítaná a lze ji použít pro vyhodnocení podmínky

HAVING používáme hlavně k zadání podmínky na základě agregační funkce

Syntaxe:

SELECT [Sloupec1],[Sloupec2], AgregacniFunkce([Sloupec3]) AS Castka
FROM Tabulka
WHERE Podminka
GROUP BY [Sloupec1],[Sloupec2]
HAVING AgregacniFunkce([Sloupec3]) <operator> Podminka

Příklady s SQL HAVING:

Tabulka [FactInternetSales] má spoustu polí jak je vidět z obrázku, ale my budeme pracovat pouze se 2-ma poli:

  • Datum [OrderDate]
  • Částka [SalesAmount]
SQL HAVING vs WHERE

Ukázková data

Podobně jako v úkolu v článku o GROUP BY budeme chtít agregovat částku podle datumů a výsledek tentokrát seřadíme vzestupně. Navíc ale budeme chtít zobrazit pouze datumy, kde součet prodejů je větší než 80 000. Použijeme k tomu:

  • agregační funkci SUM() v klauzuli SELECT
  • GROUP BY
  • HAVING
  • ORDER BY

Záměna SQL HAVING vs WHERE – Pojďme se podívat co se stane když klauzule zaměníme

Co se stane když napíšeme podmínku založenou na agregační funkci do WHERE:

SELECT [OrderDate] AS Datum
,SUM([SalesAmount]) AS Soucet
FROM [AdventureWorksDW2012].[dbo].[FactInternetSales]
WHERE SUM([SalesAmount])>80000
GROUP BY [OrderDate]
ORDER BY [OrderDate]

a výsledek nedopadl dobře

SQ HAVING vs WHERE

Ukázka použití agregační funkce ve WHERE klauzuli a následnná chybová hláška

Jak napsat skript s HAVING správně?

Místo where použijeme HAVING:

SELECT [OrderDate] AS Datum
,SUM([SalesAmount]) AS Soucet
FROM [AdventureWorksDW2012].[dbo].[FactInternetSales]
GROUP BY [OrderDate]
HAVING SUM([SalesAmount])>80000
ORDER BY [OrderDate];

Výsledek je OK:

SQL HAVING vs WHERE

Kombinace SQL HAVING vs WHERE

WHERE a HAVING se dá samozřejmě kombinovat. Budeme-li chtít například pouze Datumy od 1.1.2007 do 31.12.2007 kde součet tržeb >80 000, tak podmínku na datum uvedeme do WHERE a podmínku na agregaci do having, příklad zde:

SQL HAVING vs WHERE

Ukázka kombinování klauzulí SQL HAVING vs WHERE

Skript proběhl úspěšně bez chybové hlášky a vidíme, že mezi 1.1.2007 a 31.12.2007 nebyl ani jeden den, kde součet tržeb byl větší než 80 000. Taky výsledek =)

Reagovat na příspěvek