SQL er et sprog for databaser, og PostgreSQL er vores udvalgte sprog. Ofte er lagring af data kun én facet af processen. Typisk vil du i enhver datacentreret bestræbelse:se og læse data, handle eller implementere ændringer på dataene, indsamle information om beslutningstagning (analyse) eller manipulere de lagrede data på en eller anden måde.
SQL er sammensat af en kombination af nøgleord, kommandoer og klausuler. SQL virker simpelt. Bare et par 'lette ' kommandoer her og der. Ingen big deal, vel?
Men der er mere ved SQL, end man kan se. SQL kan slå dig op på disse 'lette ' forespørgsler.
En udfordring (som jeg rutinemæssigt skal se igen) er at forstå, at SQL-udførelsesrækkefølgen absolut er forskellig fra dens syntaks.
I dette blogindlæg besøger jeg på højt niveau de store SQL-klausuler, som de gælder for PostgreSQL. Der er mange dialekter af SQL, men PostgreSQL's fortolkning er i fokus her. (Nogle karakteristika ved hver klausul kan meget vel gælde for andre SQL-dialekter.)
SQL-sætninger danner grundlaget for grundlæggende, ofte brugte kommandoer og forespørgsler. Når det er sagt, vil avancerede forespørgsler og eksempler, der bruger vinduesfunktioner, CTE'er, afledte tabeller osv. ikke blive dækket i dette indlæg.
Som vi vil se, er ikke alle klausuler skabt lige. Alligevel fungerer de i tandem og giver forespørgselsresultater problemfrit (eller ej).
Tillad mig at præcisere...
Jeg vil med jævne mellemrum nævne en fuldbyrdelsesordre gennem hele blogindlægget, da den gælder for mange af klausulerne. Men dette er generaliseret.
Så vidt jeg forstår, vælger og beslutter optimeringsværktøjet oftest den bedste forespørgselsplan til udførelse.
SELECT - Den "kræsne" klausul, der bruges til at forespørge databasen
SELECT er en optaget klausul. Det er overalt. Brugt mere end alle de andre klausuler. Visse klausuler har du måske slet ikke brug for. Ikke så meget tilfældet med SELECT, for det er en obligatorisk klausul.
SELECT-sætningen bruges typisk til at forespørge databasen, der indeholder (på et grundlæggende niveau):
- En SELECT-liste - De kolonner med data, du ønsker.
- kildedatasættet - navngivet i FROM-sætningen. Tabeller, visninger, CTE'er osv. Det er her dataene kommer fra.
- et valgfrit WHERE-udtryk, der bruges til at filtrere rækker fra FROM-udtrykket.
(FROM- og WHERE-klausulerne vil blive diskuteret i deres respektive afsnit.)
I sandhed vil jeg sige, at SELECT-klausulen er påkrævet i PostgreSQL for at hente noget. Men så er der kommandoen TABLE, der returnerer alle rækker og kolonner fra en tabel.
Alligevel er der adskillelse mellem de to. SELECT kan angive individuelle kolonner, men med TABLE-kommandoen returneres alle kolonner.
VÆLG fremhæver:
- SELECT * er stenografi og returnerer alle kolonner fra datakilden(erne).
- Selvom SELECT syntaksmæssigt er navngivet som den første klausul (med undtagelse af de forespørgsler, der bruger en WITH-sætning:ikke diskuteret her), udføres den ikke først. Det er bemærkelsesværdigt, at SELECT heller ikke er den sidste klausul, der udføres.
- Et udtryk (eller en hvilken som helst kolonne) kan gives et referencenavn eller ALIAS i SELECT-sætningen med et forbehold. Disse fornavne kan bruges i ORDER BY og GROUP BY-sætninger, men ikke WHERE eller HAVING-sætninger.
- Når der er et GROUP BY-udtryk (eller aggregerede funktioner) i forespørgslen, bør SELECT ikke navngive nogen ikke-grupperede kolonne(r). Kun de kolonner i en eller flere aggregerede funktioner eller dem, der er funktionelt afhængige af den eller de grupperede kolonner.
- SELECT returnerer ikke kun specifikke kolonner, men dets brug omfatter også INSERT og CREATE TABLE-sætninger.
- SELECT-sætningen er langt fra enkel.
Se den officielle PostgreSQL SELECT-klausuldokumentationssektion for dybdegående dækning.
FRA - Giver datakilde(r) til forespørgslen
FROM er for det meste en obligatorisk klausul. Jeg kalder dette 'løst ' på grund af den tilgængelige TABLE-kommando (nævnt ovenfor), som ikke kræver FROM-sætningen.
Så igen kan du vælge vilkårlige udtryk uden nogen navngiven tabel i en SELECT-forespørgsel. Men med TABLE er det ikke muligt.
Her er et eksempel i psql:
learning=> SELECT 2+2;
?column?
----------
4
(1 row)
Men med TABEL:
learning=> TABLE 2+2;
ERROR: syntax error at or near "2"
LINE 1: TABLE 2+2;
^
Nogle SQL-dialekter tillader endda at navngive en ikke-eksisterende tabel for at mindske, at der ikke er en egentlig tabel i FROM-sætningen. Men i PostgreSQL, som du kan se fra den simple forespørgsel ovenfor, er det ikke påkrævet.
Men hvis du har brug for faktiske lagrede data returneret bortset fra simple udtryk, har du brug for FROM-klausulen. Uden det er der ingen data at operere på.
Derfor er FROM absolut påkrævet for at forespørge tabeller.
I Postgres bliver alle navngivne tabeller i FROM-klausulen først krydsforbundet (hvis en WITH-klausul ikke er til stede) i udførelsesordren, som etablerer et kartesisk produkt. Dette giver mening, da vi har brug for data at arbejde med.
FROM-dokumentationen her bemærker også, at dette datasæt typisk reduceres til et lille antal rækker via en nuværende WHERE-sætningsbetingelse.
FROM-klausulen accepterer en række specifikke elementer. Her er blot nogle få (se linkdokumentation nedenfor for at se den fulde liste):
- Tabelnavn (selvfølgelig har vi brug for dette).
- EN UDSIGT.
- En SELECT-sætning (en underforespørgsel).
- CTE-navn (WITH-sætning).
- Type JOIN - hvis nogen.
- En funktion (det var jeg ikke klar over. Hvor fedt!!!)
FRA højdepunkter:
- Selvom FROM er syntaktisk angivet som den anden sætning i en SELECT-forespørgsel, udføres den først.
- FROM leverer (ved at indlæse) alle rækker fra alle tabeller (virkelige eller virtuelle), der er navngivet i dens klausul.
- Tabelnavne kan have alias i FROM-sætningen (f.eks. FROM shoe AS s), men de skal refereres til af det alias i hele forespørgslen fremover.
- FROM er en obligatorisk klausul ved forespørgsler i tabeller.
Se den officielle PostgreSQL FROM-klausul for dybdegående dækning.
WHERE - Filtrerer rækker fra datakilden/datakilderne baseret på boolesk valideringsbetingede udtryk
WHERE er en valgfri klausul. Alligevel, når den er til stede i en forespørgsel, er dens pligt at fjerne de optegnelser fra FROM-klausulen, som ikke består dens booleske betingede kontrol.
WHERE-sætningen har også stor brug sammen med andre SQL-kommandoer ud over SELECT. Nemlig DML-kommandoer som INSERT (ikke direkte, men via SELECT), UPDATE og DELETE.
Faktisk ville UPDATE- og DELETE-sætninger uden en WHERE-sætning sandsynligvis påvirke alle målrækker. Måske ikke hvad du havde til hensigt (Yikes!).
Aggregerede funktioner kan ikke bruges i det booleske betingede udtryk for WHERE-udtrykket. Der er endnu ikke sket nogen gruppering i fuldbyrdelsesordren. Derfor er aggregater (endnu) ikke tilgængelige for WHERE-sætningen.
WHERE-evaluering er baseret på en boolesk kontrol ved hjælp af en af sammenligningsoperatorerne. (F.eks.>, <, =, <> osv...)
WHERE-udtrykket kan ikke få adgang til aliasede kolonnenavne, der er angivet i SELECT-udtrykket. Da SELECT-sætningen faktisk er (ikke syntaksmæssigt) udført efter WHERE-sætningen, er disse aliasede kolonner endnu ikke tilgængelige.
WHERE-højdepunkter:
- Aggregerede funktioner er ikke tilgængelige og kan ikke bruges i den boolske betingede kontrol af en WHERE-sætning. (WHERE-sætningen er muligvis ansvarlig for, at alle rækker leveres til aggregering af funktioner og gruppering til beregning.)
- Aliaserede kolonner i SELECT-udtrykket kan ikke henvises til i WHERE-udtrykket.
- WHERE-udtrykket betinget kontrol af det booleske udtryk kan resultere i enten:sand, falsk eller NULL.
- Alle rækker, hvor det booleske udtryk i WHERE-udtrykket evalueres til falsk eller NULL, fjernes.
- Flere booleske betingelser kan kontrolleres i WHERE-sætningen ved at bruge AND- eller OR-nøgleordene.
Se den officielle PostgreSQL WHERE-klausulsektion for dybdegående dækning.
GROUP BY - Forms Groups
Er en valgfri klausul.
Denne klausul opretter en enkelt række for de valgte, som indeholder et match på den angivne grupperede kolonneværdi.
GROUP BY kan være vanskelig, derfor synes jeg det er relevant at inkludere denne passage fra dokumentationen:
"Når GROUP BY er til stede, eller der findes aggregerede funktioner, er det ikke gyldigt for SELECT-listeudtrykkene at henvise til ugrupperede kolonner undtagen inden for aggregerede funktioner, eller når den ugrupperede kolonne er funktionelt afhængig af de grupperede kolonner, da der ellers ville være mere end én mulig værdi at returnere for en ugrupperet kolonne. Der eksisterer en funktionel afhængighed, hvis de grupperede kolonner (eller et undersæt deraf) er den primære nøgle i tabellen, der indeholder den ugrupperede kolonne."
GRUPPE BY højdepunkter:
- Postgres tillader gruppering af ikke kun kolonner fra kildetabellen, men også dem, der er opført i SELECT kolonnelisten. Dette er lidt anderledes end streng SQL.
- I visse forespørgsler kan GROUP BY efterligne DISTINCT-udtrykket ved at fjerne duplikerede værdier for SELECT-sætningskolonnen.
- Kolonnerækkefølgen er irrelevant for GROUP BY.
- Disse kolonner, der ikke er målrettet af GROUP BY-sætningen, kan ikke henvises til undtagen i aggregater.
- I mange tilfælde kan du gruppere på en PRIMÆR NØGLE for de funktionelt afhængige kolonner af denne nøgle.
- Gruppering udføres stadig for forespørgsler, der bruger aggregerede funktioner i fravær af en GROUP BY-klausul.
Se den officielle PostgreSQL GROUP BY-klausulsektion for dybdegående dækning.
HAVING - Filtrerer GRUPPER EFTER kolonne(r) og aggregerede funktioner
Er en valgfri klausul.
HAVING filtrerer rækker fra resultaterne sat med en boolsk betinget kontrol ligesom WHERE-udtrykket, bortset fra, at det filtrerer de rækker, der er dannet af GROUP BY-udtrykket og/eller aggregerede funktioner.
HAR højdepunkter:
- HAVING-sætningen kan henvise til de kolonner, der er navngivet i aggregerede funktioner (selv dem, der ikke er grupperet) ud over alle GROUP BY-kolonner.
- HAVING er ansvarlig for at fjerne rækker, efter at aggregerede funktioner eller gruppering er blevet anvendt.
- Du kan referere til ikke-aggregerede kolonner i HAVING-sætningen, selvom det kun har meget lidt nytte at gøre det.
- Selvom HAVING-sætningen mange gange bruges sammen med GROUP BY-sætningen, kan du bruge den alene. Forespørgselsresultater dannes kun i en enkelt gruppe af disse kolonner i aggregerede funktioner.
Se den officielle PostgreSQL HAVING-klausulsektion for dybdegående dækning.
ORDER BY - A Measure of Order Out of Randomness
Er en valgfri klausul.
Brug BESTIL BY, når du har brug for specifik bestilling. Ellers kan (og vil) databasen returnere resultater i enhver vilkårlig rækkefølge.
Selv hvis resultaterne ser ud til at være i en vis orden, er dette ikke garanteret.
Lad dig ikke narre. Brug BESTIL EFTER.
Der er to tilgængelige bestillingsmønstre. Enten ASC (stigende) eller DESC (faldende) rækkefølge, hvor ASC er standard.
Hvis dit resultatsæt skal inkludere NULL-værdier, kan disse også bruges i rækkefølgen som følger:Angivelse af NULLS LAST får dem (NULLs) til at sortere efter ikke-NULLs, mens anmodning om NULLS FIRST er det omvendte.
BESTIL EFTER højdepunkter:
- Sorteringsudtryk er enhver af dem, der ville være tilladt i SELECT-listen for forespørgslen.
- PostgreSQL giver dig mulighed for at ORDER BY kolonner, der ikke findes i SELECT-sætningen, hvor nogle SQL-dialekter ikke gør det.
- Forespørgselsresultater er lunefulde og kan ikke garanteres at ligne noget mønster eller en rækkefølge, medmindre der bruges en ORDER BY-klausul.
- ORDER BY og LIMIT-sætningen (se næste afsnit) er gode kombineret til at bestemme en 'Top ' række resultater sæt. (f.eks. 5 dage med højeste udsalg, 5 par sko, der sælger lavest, topsælger i dette kvartal)
- Du kan bestille resultater efter kolonnepositionsnummer i SELECT-listen, men det angivne antal må ikke være større end antallet af elementer i nævnte SELECT-sætningsliste. Med andre ord, hvis SELECT-sætningen kun har 2 elementer, vil ORDER BY 3 give en fejl.
- Hvert individuelt udtryk er kun sorteret efter dets angivne valgmulighed. (f.eks. ORDER BY col_1 DESC, col_2 DESC er ikke det samme som ORDER BY col_1, col_2 DESC)
Se den officielle PostgreSQL ORDER BY-klausulsektion for dybdegående dækning.
Download Whitepaper Today PostgreSQL Management &Automation med ClusterControlFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere PostgreSQLDownload WhitepaperLIMIT - Hent et bestemt antal rækker fra forespørgselsresultaterne
LIMIT er en valgfri klausul.
LIMIT består faktisk af 2 underklausuler, hvor OFFSET er den anden af dem.
Hvis der er angivet en værdi for OFFSET-delen af klausulen, returneres rækker i resultatsæt efter springer det antal rækker over.
Et vigtigt afsnit i dokumentationen at bemærke:
"Forespørgselsplanlæggeren tager højde for LIMIT, når du genererer en forespørgselsplan, så du er meget sandsynligt, at du får forskellige planer (der giver forskellige rækkefølger) afhængigt af, hvad du bruger til LIMIT og OFFSET. Bruger således forskellige LIMIT/OFFSET-værdier til at vælge forskellige undersæt af et forespørgselsresultat vil give inkonsistente resultater, medmindre du gennemtvinger en forudsigelig resultatbestilling med ORDER BY. Dette er ikke en fejl; det er en iboende konsekvens af det faktum, at SQL ikke lover at levere resultaterne af en forespørgsel i nogen bestemt rækkefølge medmindre ORDER BY bruges til at begrænse ordren."
LIMIT højdepunkter:
- LIMIT kan muligvis returnere færre rækker end det definerede antal, hvis forespørgslen i sig selv producerer færre rækker i resultatsættet. Med andre ord ville det ikke have nogen indflydelse på antallet af returnerede rækker.
- LIMIT ALL syntaks er acceptabel og har samme effekt som slet ikke at inkludere en LIMIT-sætning.
- Selvom 'x' antal rækker springes over på grund af en OFFSET-klausul, er dette ikke en 'løsning ' for enhver præstationsgevinst, da de stadig beregnes til forespørgselsplanen på serveren.
- OFFSET 0 svarer til slet ikke at inkludere en OFFSET-klausul.
Se den officielle PostgreSQL LIMIT-klausul for dybdegående dækning.
PostgreSQL's fortolkning af de store SQL-klausuler er sin egen. Uanset hvordan PostgreSQL vælger at implementere dem eller ej, er de grundlæggende for SQL-forespørgsler, og kendskab til deres individuelle karakteristika (og nuancer) kan kun gavne brugerne fremover.
Selvom der er skrevet mængder af artikler, bøger, dokumentation og blogindlæg om hver af disse klausuler, håber jeg, at du finder denne oversigt på højt niveau fordøjelig og informativ.
Tak fordi du læste med.