SQL is een taal van databases en PostgreSQL is onze gekozen taal. Vaak is het opslaan van gegevens maar één facet van het proces. Doorgaans zult u bij elke datacentrische onderneming:gegevens bekijken en lezen, actie ondernemen of wijzigingen doorvoeren in de gegevens, besluitvormingsinformatie verzamelen (analyse) of de opgeslagen gegevens op een of andere manier manipuleren.
SQL is samengesteld uit een combinatie van trefwoorden, opdrachten en clausules. SQL lijkt eenvoudig. Slechts een paar 'eenvoudige ' commando's hier en daar. Geen probleem, toch?
Maar SQL is meer dan op het eerste gezicht lijkt. SQL kan je laten struikelen over die 'gemakkelijke ' vragen.
Een uitdaging (die ik regelmatig opnieuw moet bekijken) is om te begrijpen dat de SQL-uitvoeringsvolgorde absoluut verschilt van die van de syntaxis.
In deze blogpost bezoek ik op hoog niveau de belangrijkste SQL-clausules zoals ze van toepassing zijn op PostgreSQL. Er zijn veel dialecten van SQL, maar de interpretatie van PostgreSQL staat hier centraal. (Sommige kenmerken van elke clausule kunnen heel goed van toepassing zijn op andere SQL-dialecten.)
SQL-clausules vormen de basis voor elementaire, veelgebruikte opdrachten en query's. Dat gezegd hebbende, geavanceerde vragen en voorbeelden die gebruikmaken van vensterfuncties, CTE's, afgeleide tabellen, enz. worden niet behandeld in dit bericht.
Zoals we zullen zien, zijn niet alle clausules gelijk gemaakt. Toch werken ze samen en leveren ze naadloos (of niet) queryresultaten.
Sta me toe om te verduidelijken...
Ik zal in de blogpost regelmatig melding maken van een uitvoeringsbevel, aangezien dit van toepassing is op veel van de clausules. Maar dit is algemeen.
Voor zover ik weet, kiest en beslist de optimizer vaker wel dan niet het beste queryplan voor uitvoering.
SELECT - De 'kieskeurige' clausule die wordt gebruikt om de database te doorzoeken
SELECT is een drukke clausule. Het is overal. Meer gebruikt dan alle andere clausules. Bepaalde clausules heb je misschien helemaal niet nodig. Niet zozeer het geval met SELECT, want het is een verplichte clausule.
De SELECT-component wordt meestal gebruikt voor het opvragen van de database, met (op basisniveau):
- Een SELECT-lijst - De kolommen met gegevens die u wilt.
- de brongegevensset(s) - genoemd in de FROM-clausule. Tabellen, weergaven, CTE's, enz. Hier komen de gegevens vandaan.
- een optionele WHERE-component die wordt gebruikt om rijen te filteren die door de FROM-component worden geleverd.
(De FROM- en WHERE-clausules zullen in hun respectievelijke secties worden besproken.)
In werkelijkheid zou ik zeggen dat de SELECT-clausule in PostgreSQL vereist is om iets op te halen. Maar dan is er het TABLE-commando dat alle rijen en kolommen uit een tabel retourneert.
Toch is er een scheiding tussen de twee. SELECT kan individuele kolommen specificeren, maar met het TABLE commando worden alle kolommen geretourneerd.
SELECT hoogtepunten:
- SELECT * is een verkorte notatie en retourneert alle kolommen van de gegevensbron(nen).
- Hoewel SELECT syntaxismatig als de eerste clausule wordt genoemd (met uitzondering van die query's die een WITH-clausule gebruiken:hier niet besproken), wordt het niet als eerste uitgevoerd. Opmerkelijk is dat SELECT ook niet de laatste clausule is die moet worden uitgevoerd.
- Een expressie (of een willekeurige kolom) kan een referentienaam of ALIAS krijgen in de SELECT-component, met een waarschuwing. Die voornamen kunnen worden gebruikt in ORDER BY- en GROUP BY-clausules, maar niet in WHERE- of HAVING-clausules.
- Als een GROUP BY-clausule aanwezig is (of aggregatiefuncties) in de query, mag SELECT geen naam geven aan niet-gegroepeerde kolom(men). Alleen die kolommen in een geaggregeerde functie(s) of die welke functioneel afhankelijk zijn van de gegroepeerde kolom(men).
- Niet alleen retourneert SELECT specifieke kolommen, maar het gebruik ervan strekt zich ook uit tot INSERT- en CREATE TABLE-statements.
- De SELECT-clausule is verre van eenvoudig.
Zie de documentatiesectie van de officiële PostgreSQL SELECT-clausule voor diepgaande dekking.
FROM - Biedt de gegevensbron(nen) voor de query
FROM is meestal een dwingende clausule. Ik noem dit 'losjes ' vanwege het beschikbare TABLE-commando (hierboven vermeld), waarvoor de FROM-clausule niet vereist is.
Aan de andere kant kunt u willekeurige expressies selecteren, zonder benoemde tabel in een SELECT-query. Met TABLE is dat echter niet mogelijk.
Hier is een voorbeeld in psql:
learning=> SELECT 2+2;
?column?
----------
4
(1 row)
Maar met TABEL:
learning=> TABLE 2+2;
ERROR: syntax error at or near "2"
LINE 1: TABLE 2+2;
^
Sommige SQL-dialecten maken het zelfs mogelijk om een niet-bestaande tabel een naam te geven om het ontbreken van een echte tabel in de FROM-clausule te voorkomen. Maar in PostgreSQL, zoals u kunt zien aan de hand van de eenvoudige vraag hierboven, is dit niet vereist.
Maar als u daadwerkelijk opgeslagen gegevens wilt retourneren, afgezien van eenvoudige expressies, hebt u de FROM-component nodig. Zonder dit zijn er zelfs geen gegevens om mee te werken.
Daarom is FROM absoluut vereist voor het opvragen van tabellen.
In Postgres worden alle benoemde tabellen in de FROM-clausule eerst gekruist (als er geen WITH-clausule aanwezig is) in de uitvoeringsvolgorde die een Cartesiaans product tot stand brengt. Dit is logisch, aangezien we gegevens nodig hebben om mee te werken.
De FROM-documentatie hier merkt ook op dat deze dataset doorgaans wordt teruggebracht tot een klein aantal rijen via een aanwezige WHERE-clausulevoorwaarde.
De FROM-clausule accepteert een aantal specifieke elementen. Hier zijn er slechts een paar (zie de koppelingsdocumentatie hieronder voor de volledige lijst):
- Tabelnaam (uiteraard hebben we deze nodig).
- EEN UITZICHT.
- Een SELECT-instructie (een subquery).
- CTE-naam (WITH-clausule).
- Type JOIN - indien van toepassing.
- Een functie (ik was me hier niet van bewust. Wat gaaf!!!)
VAN hoogtepunten:
- Hoewel FROM syntactisch wordt vermeld als de tweede clausule in een SELECT-query, wordt deze als eerste uitgevoerd.
- FROM biedt (door te laden) alle rijen van alle tabellen (reëel of virtueel) die in de bijbehorende clausule worden genoemd.
- Tabelnamen kunnen een alias zijn in de FROM-component (bijv. FROM shoe AS s) maar er moet naar verwezen worden door die ALIAS tijdens de verdere query.
- FROM is een verplichte clausule bij het opvragen van tabellen.
Zie de sectie Official PostgreSQL FROM-clausule voor diepgaande informatie.
WHERE - Filtert rijen uit de gegevensbron(nen) op basis van Booleaanse validatie voorwaardelijke expressie(s)
WHERE is een optionele clausule. Maar wanneer aanwezig in een query, is het zijn taak om die records te verwijderen die worden geleverd door de FROM-clausule die de booleaanse voorwaardelijke controle niet doorstaan.
De WHERE-component heeft naast SELECT ook veel nut met andere SQL-opdrachten. Namelijk DML-commando's zoals INSERT (niet rechtstreeks, maar via SELECT), UPDATE en DELETE.
Zonder een WHERE-clausule zouden de instructies UPDATE en DELETE waarschijnlijk van invloed zijn op alle doelrijen. Misschien niet wat je van plan was (Yikes!).
Geaggregeerde functies kunnen niet worden gebruikt in de booleaanse voorwaardelijke expressie van de WHERE-component. Er heeft nog geen groepering plaatsgevonden in de uitvoeringsvolgorde. Daarom zijn er (nog) geen aggregaten beschikbaar voor de WHERE-clausule.
WHERE-evaluatie is gebaseerd op een booleaanse controle met behulp van een van de vergelijkingsoperatoren. (Bijvoorbeeld>, <, =, <>, enz...)
De WHERE-component heeft geen toegang tot kolomnamen met aliassen die worden vermeld in de SELECT-component. Aangezien de SELECT-component eigenlijk . is (niet syntaxisgewijs) uitgevoerd na de WHERE-component, zijn die gealiaste kolommen nog niet beschikbaar.
WAAR hoogtepunten:
- Geaggregeerde functies zijn niet toegankelijk en kunnen niet worden gebruikt bij de booleaanse voorwaardelijke controle van een WHERE-component. (De WHERE-clausule is mogelijk verantwoordelijk voor alle rijen die worden geleverd om functies te aggregeren en te groeperen voor berekening.)
- Gealiaste kolommen in de SELECT-component kunnen niet worden verwezen in de WHERE-component.
- De WHERE-clausule booleaanse expressie voorwaardelijke controle kan resulteren in:waar, onwaar of NULL.
- Alle rijen waarin de WHERE-component booleaanse expressie wordt geëvalueerd als false of NULL, worden verwijderd.
- Meerdere booleaanse voorwaarden kunnen worden gecontroleerd in de WHERE-clausule door gebruik te maken van de trefwoorden AND of OR.
Zie de sectie Official PostgreSQL WHERE-clausule voor diepgaande dekking.
GROUP BY - Formulieren Groepen
Is een optionele clausule.
Deze clausule creëert een enkele rij voor de geselecteerde, die een overeenkomst bevat met de gespecificeerde gegroepeerde kolomwaarde.
GROUP BY kan lastig zijn, daarom vind ik het relevant om deze passage uit de documentatie op te nemen:
"Als GROUP BY aanwezig is of als er geaggregeerde functies aanwezig zijn, is het niet geldig dat de expressies van de SELECT-lijst verwijzen naar niet-gegroepeerde kolommen, behalve binnen geaggregeerde functies of wanneer de niet-gegroepeerde kolom functioneel afhankelijk is van de gegroepeerde kolommen, omdat er anders meer dan één mogelijke waarde om te retourneren voor een niet-gegroepeerde kolom. Er bestaat een functionele afhankelijkheid als de gegroepeerde kolommen (of een subset daarvan) de primaire sleutel zijn van de tabel die de niet-gegroepeerde kolom bevat."
GROUP BY hoogtepunten:
- Postgres staat het groeperen van niet alleen kolommen uit de brontabel toe, maar ook die welke in de SELECT-kolomlijst staan. Dit is iets anders dan strikte SQL.
- In bepaalde zoekopdrachten kan GROUP BY de DISTINCT-component nabootsen door dubbele waarden voor de SELECT-componentkolom te verwijderen.
- Kolomvolgorde is niet relevant voor GROUP BY.
- Er kan niet worden verwezen naar kolommen die niet worden getarget door de GROUP BY-clausule, behalve in aggregaten.
- In veel gevallen kunt u groeperen op een PRIMAIRE SLEUTEL voor die functioneel afhankelijke kolommen van die sleutel.
- Groepering wordt nog steeds uitgevoerd voor query's die gebruik maken van geaggregeerde functies bij afwezigheid van een GROUP BY-clausule.
Zie de sectie Official PostgreSQL GROUP BY-clausule voor diepgaande dekking.
HAVING - Filters GROEP OP kolom(men) en aggregatiefuncties
Is een optionele clausule.
HAVING filtert rijen uit de resultatenset met een booleaanse voorwaardelijke controle, net als de WHERE-component, behalve dat het de rijen filtert die worden gevormd door de GROUP BY-component en/of aggregatiefuncties.
MET hoogtepunten:
- De HAVING-component kan verwijzen naar de kolommen die genoemd zijn in statistische functies (zelfs die niet gegroepeerd zijn), naast eventuele GROUP BY-kolommen.
- HAVING is verantwoordelijk voor het verwijderen van rijen nadat aggregatiefuncties of groepering zijn toegepast.
- U kunt verwijzen naar niet-geaggregeerde kolommen in de HAVING-component, hoewel dit weinig zin heeft.
- Hoewel de HAVING-component vaak wordt gebruikt in combinatie met de GROUP BY-component, kunt u deze ook alleen gebruiken. Queryresultaten worden alleen in geaggregeerde functies gevormd tot een enkele groep van die kolommen.
Zie de sectie Official PostgreSQL HAVING-clausule voor diepgaande dekking.
ORDER BY - Een mate van volgorde uit willekeur
Is een optionele clausule.
Gebruik ORDER BY wanneer u een specifieke bestelling nodig heeft. Anders kan (en zal) de database resultaten retourneren in willekeurige volgorde.
Zelfs als de resultaten in een bepaalde volgorde lijken te staan, is dit niet gegarandeerd.
Laat je niet misleiden. Gebruik ORDER BY.
Er zijn twee beschikbare bestelpatronen. Ofwel ASC (oplopend) of DESC (aflopend) volgorde, waarbij ASC de standaard is.
Als uw resultatenset NULL-waarden moet bevatten, kunnen deze ook als volgt in de volgorde worden gebruikt:als u NULLS LAST opgeeft, worden deze (NULL's) gesorteerd op niet-NULL-waarden, terwijl het opvragen van NULLS EERST het omgekeerde is.
ORDER BY hoogtepunten:
- Sorteerexpressie(s) zijn een van de expressie(s) die zouden zijn toegestaan in de SELECT-lijst van de zoekopdracht.
- PostgreSQL staat je toe kolommen te ORDER BY-tekenen die niet aanwezig zijn in de SELECT-clausule, waar sommige SQL-dialecten dat niet doen.
- Zoekresultaten zijn grillig en zullen niet gegarandeerd lijken op een patroon of volgorde, tenzij een ORDER BY-clausule wordt gebruikt.
- ORDER BY en de LIMIT-clausule (zie volgende sectie), zijn geweldig gecombineerd voor het bepalen van een 'Top ' rijen resultaten ingesteld. (bijv. 5 best verkochte dagen, 5 best verkochte paar schoenen, topverkoper dit kwartaal)
- U kunt resultaten sorteren op kolompositienummer in de SELECT-lijst, maar het opgegeven aantal mag niet groter zijn dan het aantal items in de SELECT-clausulelijst. Met andere woorden, als de SELECT-clausule slechts 2 items heeft, zal ORDER BY 3 een fout produceren.
- Elke individuele expressie wordt alleen geordend op de vermelde optie. (bijv. ORDER BY col_1 DESC, col_2 DESC is niet hetzelfde als ORDER BY col_1, col_2 DESC)
Zie de sectie Official PostgreSQL ORDER BY-clausule voor diepgaande dekking.
Download de whitepaper vandaag PostgreSQL-beheer en -automatisering met ClusterControlLees wat u moet weten om PostgreSQL te implementeren, bewaken, beheren en schalenDownload de whitepaperLIMIET - Haal een specifiek aantal rijen op uit de queryresultaten
LIMIT is een optionele clausule.
LIMIT bestaat eigenlijk uit 2 sub-clausules, waarvan OFFSET de tweede is.
Als er een waarde is opgegeven voor het OFFSET-gedeelte van de clausule, worden rijen met resultatenset geretourneerd na dat aantal rijen overslaan.
Een belangrijk onderdeel in de documentatie om op te merken:
"De queryplanner houdt rekening met LIMIT bij het genereren van een queryplan, dus het is zeer waarschijnlijk dat u verschillende plannen krijgt (die verschillende rijvolgordes opleveren), afhankelijk van wat u gebruikt voor LIMIT en OFFSET. Dus, door verschillende LIMIT/OFFSET-waarden te gebruiken om verschillende subsets van een queryresultaat geven inconsistente resultaten, tenzij u een voorspelbare resultaatvolgorde afdwingt met ORDER BY. Dit is geen bug; het is een inherent gevolg van het feit dat SQL niet belooft de resultaten van een query in een bepaalde volgorde te leveren tenzij ORDER BY wordt gebruikt om de bestelling te beperken."
LIMIT hoogtepunten:
- LIMIT kan mogelijk minder rijen retourneren dan het gedefinieerde aantal als de query zelf minder rijen in de resultatenset produceert. Met andere woorden, het zou geen invloed hebben op het aantal geretourneerde rijen.
- De syntaxis van LIMIT ALL is acceptabel en heeft hetzelfde effect als het helemaal niet opnemen van een LIMIT-clausule.
- Hoewel 'x' aantal rijen wordt overgeslagen vanwege een OFFSET-clausule, is dit geen 'oplossing ' voor prestatiewinst, omdat ze nog steeds worden berekend voor het queryplan op de server.
- OFFSET 0 is gelijk aan het helemaal niet opnemen van een OFFSET-clausule.
Zie de sectie Officiële PostgreSQL LIMIT-clausule voor diepgaande dekking.
PostgreSQL's interpretatie van de belangrijkste SQL-clausules is die van hemzelf. Ongeacht hoe PostgreSQL ervoor kiest om ze te implementeren of niet, ze zijn van fundamenteel belang voor SQL-query's en vertrouwdheid met hun individuele kenmerken (en nuances) kan alleen maar voordelen opleveren voor gebruikers in de toekomst.
Hoewel er over elk van deze clausules grote hoeveelheden artikelen, boeken, documentatie en blogposts zijn geschreven, hoop ik dat u dit overzicht op hoog niveau verteerbaar en informatief vindt.
Bedankt voor het lezen.