i denne artikel lærer du, hvornår du skal bruge hvor og have. Begge udfører lignende funktioner, men til forskellige formål!
alle eksemplerne til denne artikel er baseret på Microsoft Server Management Studio og Adventurearbejds2012-databasen. Du kan komme i gang med at bruge disse gratis værktøjer ved hjælp af min Guide.
Hvordan gør hvor og har forskellige?
når du arbejder med mere avanceret KVL, kan det være uklart, hvornår det giver mening at bruge en hvor versus en have-klausul.
selvom det ser ud til, at begge klausuler gør det samme, gør de det på forskellige måder. Faktisk supplerer deres funktioner hinanden.
- A hvor klausul bruges, er filterposter fra et resultat. Filteret opstår, før der foretages grupperinger.
- en have-klausul bruges til at filtrere værdier fra en gruppe.
før vi går videre, lad os gennemgå formatet af en KVL-Erklæring. Det er
SELECTFROMWHEREGROUP BYHAVING
for at hjælpe med at holde tingene lige, jeg kan godt lide at tænke på rækkefølgen af udførelse af KVM-udsagn fra top til bund. Det betyder, hvor klausulen først anvendes på resultatet og derefter, de resterende rækker opsummeret i henhold til gruppen af.
hvor klausul
hvor klausul bruges til at filtrere rækker fra resultater. For eksempel
SELECT COUNT(SalesOrderID)FROM Sales.SalesOrderDetail
returnerer 121,317 fra tællingen, mens forespørgslen
SELECT COUNT(SalesOrderID)FROM Sales.SalesOrderDetailWHERE UnitPrice > 200
returnerer 48,159 som tællingen. Dette er på grund af hvor klausul filtrerer ud 73,158 SalesOrderDetails hvis UnitPrice er mindre end eller lig med 200 fra resultaterne.
have Klausul
have klausul bruges til at filtrere værdier i en gruppe efter. Du kan bruge dem til at filtrere grupper som
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SalesOrderID > 50000
, men deres sande kraft ligger i deres evne til at sammenligne og filtrere baseret på aggregatfunktionsresultater. For eksempel kan du vælge alle ordrer i alt mere end $10,000
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
da hvor-klausulens synlighed er en række ad gangen, er der ikke en måde for den at evaluere summen på tværs af alle SalesOrderID ‘ er. have-klausulen evalueres, når grupperingen er oprettet.
kombination af de to: Hvor og at have
når KVL-udsagn har både en hvor-klausul og have-klausul, skal du huske hvor-klausulen først anvendes, derefter grupperes resultaterne, og endelig filtreres grupperne i henhold til have-klausulen.
i mange tilfælde kan du placere hvor-betingelsen i have-klausulen, såsom
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000 AND SalesOrderID > 50000
Versus
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailWHERE SalesOrderID > 50000GROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
hvis du kan sætte betingelse fra hvor-klausulen i have-klausulen, hvorfor så bekymre dig om hvor? Kan jeg bare bruge denne forespørgsel?
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailGROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000 AND LineTotal > 10
faktisk genererer denne forespørgsel en fejl. Kolonnelinjetotalen er ikke en del af listen gruppe efter felt eller resultatet af en samlet total.
for at være gyldig kan have-klausulen kun sammenligne resultater af aggregerede funktioner eller kolonnedel af gruppen med.
for at være gyldig skal forespørgslen omskrives som
SELECT SalesOrderID, SUM(UnitPrice * OrderQty) AS TotalPriceFROM Sales.SalesOrderDetailWHERE LineTotal > 100GROUP BY SalesOrderIDHAVING SUM(UnitPrice * OrderQty) > 10000
for at opsummere forskellen mellem hvor og have:
- hvor bruges til at filtrere poster, før nogen grupperinger finder sted.
- at have bruges til at filtrere værdier, efter at de har været grupper. Kun kolonner eller udtryk i gruppen kan inkluderes i HAVING-klausulens betingelser …