SQL est un langage de bases de données et PostgreSQL est notre préféré. Souvent, le stockage des données n'est qu'une facette du processus. En règle générale, dans toute entreprise centrée sur les données, vous devez :afficher et lire des données, prendre des mesures ou mettre en œuvre des modifications sur les données, recueillir des informations décisionnelles (analyses) ou manipuler les données stockées sous une forme ou d'une manière.
SQL est composé d'une combinaison de mots-clés, de commandes et de clauses. SQL semble simple. Juste quelques 'facile ' commandes ici et là. Ce n'est pas grave, n'est-ce pas ?
Mais, il y a plus dans SQL qu'il n'y paraît. SQL peut vous faire trébucher sur ces 'faciles ' requêtes.
Un défi (que je dois régulièrement revoir) est de comprendre que l'ordre d'exécution SQL est définitivement différent de celui de sa syntaxe.
Dans cet article de blog, je visite, à un niveau élevé, les principales clauses SQL telles qu'elles s'appliquent à PostgreSQL. Il existe de nombreux dialectes de SQL, mais l'interprétation de PostgreSQL est au centre des préoccupations ici. (Certaines caractéristiques de chaque clause peuvent très bien s'appliquer à d'autres dialectes SQL.)
Les clauses SQL constituent la base des commandes et requêtes de base souvent utilisées. Cela étant dit, les requêtes avancées et les exemples utilisant les fonctions de fenêtre, les CTE, les tables dérivées, etc. ne seront pas couverts dans cet article.
Comme nous le verrons, toutes les clauses ne sont pas égales. Pourtant, ils fonctionnent en tandem, fournissant des résultats de requête de manière transparente (ou non).
Permettez-moi de clarifier...
Je mentionnerai périodiquement un ordre d'exécution tout au long du billet de blog car il s'applique à de nombreuses clauses. Mais c'est généralisé.
À ma connaissance, le plus souvent, l'optimiseur choisit et décide du meilleur plan de requête à exécuter.
SELECT - La clause 'picky' utilisée pour interroger la base de données
SELECT est une clause occupée. C'est partout. Utilisé plus que toutes les autres clauses. Certaines clauses dont vous n'avez peut-être pas du tout besoin. Ce n'est pas tellement le cas avec SELECT, car c'est une clause obligatoire.
La clause SELECT est généralement utilisée pour interroger la base de données, contenant (à un niveau de base) :
- Une liste SELECT :les colonnes de données souhaitées.
- le ou les ensembles de données source - nommés dans la clause FROM. Tables, vues, CTE, etc. C'est de là que viennent les données.
- une clause WHERE facultative utilisée pour filtrer les lignes fournies par la clause FROM.
(Les clauses FROM et WHERE seront abordées dans leurs sections respectives.)
En vérité, je dirais que la clause SELECT est requise dans PostgreSQL pour récupérer quoi que ce soit. Mais ensuite, il y a la commande TABLE qui renvoie toutes les lignes et colonnes d'une table.
Pourtant, il y a séparation entre les deux. SELECT peut spécifier des colonnes individuelles, mais avec la commande TABLE, toutes les colonnes sont renvoyées.
SÉLECTIONNER les faits saillants :
- SELECT * est une notation abrégée et renvoie toutes les colonnes de la ou des sources de données.
- Bien que SELECT soit syntaxiquement nommé comme première clause (à l'exception des requêtes utilisant une clause WITH :non abordées ici), il n'est pas exécuté en premier. Notamment, SELECT n'est pas non plus la dernière clause à exécuter.
- Une expression (ou n'importe quelle colonne) peut recevoir un nom de référence ou ALIAS dans la clause SELECT, avec une mise en garde. Ces prénoms peuvent être utilisés dans les clauses ORDER BY et GROUP BY mais pas dans les clauses WHERE ou HAVING.
- Lorsqu'une clause GROUP BY est présente (ou des fonctions d'agrégation) dans la requête, SELECT ne doit nommer aucune colonne non groupée. Uniquement les colonnes de toute fonction d'agrégation ou celles qui dépendent fonctionnellement de la ou des colonnes groupées.
- Non seulement SELECT renvoie des colonnes spécifiques, mais son utilisation s'étend également aux instructions INSERT et CREATE TABLE.
- La clause SELECT est loin d'être simple.
Consultez la section de documentation officielle de la clause PostgreSQL SELECT pour une couverture détaillée.
FROM - Fournit la ou les sources de données pour la requête
FROM est principalement une clause obligatoire. J'appelle cela 'vaguement ' à cause de la commande TABLE disponible (mentionnée ci-dessus), qui ne nécessite pas la clause FROM.
Là encore, vous pouvez sélectionner des expressions arbitraires, sans table nommée dans une requête SELECT. Cependant, avec TABLE, ce n'est pas possible.
Voici un exemple en psql :
learning=> SELECT 2+2;
?column?
----------
4
(1 row)
Mais avec TABLE :
learning=> TABLE 2+2;
ERROR: syntax error at or near "2"
LINE 1: TABLE 2+2;
^
Certains dialectes SQL permettent même de nommer une table inexistante pour atténuer le fait de ne pas avoir de table réelle dans la clause FROM. Pourtant, dans PostgreSQL, comme vous pouvez le voir à partir de la simple requête ci-dessus, ce n'est pas obligatoire.
Mais, si vous avez besoin de données stockées réelles renvoyées en dehors d'expressions simples, vous aurez besoin de la clause FROM. Sans cela, il n'y a même pas de données sur lesquelles opérer.
Par conséquent, FROM est absolument nécessaire pour interroger n'importe quelle table.
Dans Postgres, toutes les tables nommées dans la clause FROM sont d'abord croisées (si une clause WITH n'est pas présente) dans l'ordre d'exécution qui établit un produit cartésien. Cela a du sens puisque nous avons besoin de données pour travailler avec.
La documentation FROM ici note également que, généralement, cet ensemble de données est réduit à un petit nombre de lignes via une condition de clause WHERE présente.
La clause FROM accepte un certain nombre d'éléments spécifiques. En voici quelques-unes (voir la documentation de liaison ci-dessous pour la liste complète) :
- Nom de la table (évidemment, nous en avons besoin).
- UNE VUE.
- Une instruction SELECT (une sous-requête).
- Nom CTE (clause WITH).
- Type de JOIN - le cas échéant.
- Une fonction (je n'étais pas au courant. Comme c'est cool !)
DE faits saillants :
- Bien que FROM soit syntaxiquement répertorié comme la deuxième clause d'une requête SELECT, il est exécuté en premier.
- FROM fournit (en chargeant) toutes les lignes de toutes les tables (réelles ou virtuelles) nommées dans sa clause.
- Les noms de table peuvent être associés à un alias dans la clause FROM (par exemple, FROM shoe AS s) mais doivent être référencés par cet ALIAS tout au long de la requête.
- FROM est une clause obligatoire lors de l'interrogation de tables.
Consultez la section de la clause FROM officielle de PostgreSQL pour une couverture détaillée.
WHERE - Filtre les lignes des sources de données en fonction des expressions conditionnelles de validation booléenne
WHERE est une clause facultative. Pourtant, lorsqu'il est présent dans une requête, son devoir est de supprimer les enregistrements fournis par la clause FROM qui ne réussissent pas sa vérification conditionnelle booléenne.
La clause WHERE a également une utilisation approfondie avec d'autres commandes SQL en plus de SELECT. À savoir, les commandes DML telles que INSERT (pas directement, mais via SELECT), UPDATE et DELETE.
En fait, sans clause WHERE, les instructions UPDATE et DELETE affecteraient probablement toutes les lignes cibles. Peut-être pas ce que vous vouliez (Yikes !).
Les fonctions d'agrégation ne peuvent pas être utilisées dans l'expression conditionnelle booléenne de la clause WHERE. Aucun regroupement n'a encore eu lieu dans l'ordre d'exécution. Par conséquent, les agrégats ne sont pas (encore) disponibles pour la clause WHERE.
L'évaluation WHERE est basée sur une vérification booléenne utilisant l'un des opérateurs de comparaison. (Par exemple,>, <, =, <>, etc…)
La clause WHERE ne peut pas accéder aux noms de colonnes avec alias répertoriés dans la clause SELECT. Puisque la clause SELECT est en fait (pas du point de vue de la syntaxe) exécutées après la clause WHERE, ces colonnes aliasées ne sont pas encore disponibles.
OÙ met en évidence :
- Les fonctions d'agrégation ne sont pas accessibles et ne peuvent pas être utilisées dans la vérification conditionnelle booléenne d'une clause WHERE. (La clause WHERE est peut-être responsable de toutes les lignes fournies pour agréger les fonctions et les regrouper pour le calcul.)
- Les colonnes avec alias dans la clause SELECT ne peuvent pas être référencées dans la clause WHERE.
- La vérification conditionnelle de l'expression booléenne de la clause WHERE peut donner soit :vrai, faux ou NULL.
- Toutes les lignes dans lesquelles l'expression booléenne de la clause WHERE prend la valeur false ou NULL sont supprimées.
- Plusieurs conditions booléennes peuvent être vérifiées dans la clause WHERE en utilisant les mots-clés AND ou OR.
Consultez la section sur la clause WHERE officielle de PostgreSQL pour une couverture détaillée.
GROUPER PAR - Groupes de formulaires
Est une clause facultative.
Cette clause crée une seule ligne pour ceux sélectionnés, qui contient une correspondance sur la valeur de colonne groupée spécifiée.
GROUP BY peut être délicat, par conséquent, je pense qu'il est pertinent d'inclure ce passage de la documentation :
"Lorsque GROUP BY est présent, ou que des fonctions d'agrégation sont présentes, il n'est pas valide que les expressions de liste SELECT se réfèrent à des colonnes non groupées, sauf dans les fonctions d'agrégation ou lorsque la colonne non groupée dépend fonctionnellement des colonnes groupées, car il y aurait autrement plusieurs valeurs possibles à renvoyer pour une colonne non groupée. Une dépendance fonctionnelle existe si les colonnes groupées (ou un sous-ensemble de celles-ci) sont la clé primaire de la table contenant la colonne non groupée."
GROUP BY met en évidence :
- Postgres permet de regrouper non seulement les colonnes de la table source, mais également celles répertoriées dans la liste de colonnes SELECT. Ceci est légèrement différent du SQL strict.
- Dans certaines requêtes, GROUP BY peut imiter la clause DISTINCT en supprimant les valeurs en double pour la colonne de la clause SELECT.
- L'ordre des colonnes n'est pas pertinent pour GROUP BY.
- Les colonnes non ciblées par la clause GROUP BY ne peuvent être référencées que dans des agrégats.
- Dans de nombreux cas, vous pouvez effectuer un regroupement sur une CLÉ PRIMAIRE pour les colonnes fonctionnellement dépendantes de cette clé.
- Le regroupement est toujours effectué pour les requêtes utilisant des fonctions d'agrégation en l'absence de clause GROUP BY.
Consultez la section officielle de la clause GROUP BY de PostgreSQL pour une couverture détaillée.
HAVING - Filtre les colonnes GROUP BY et les fonctions d'agrégation
Est une clause facultative.
HAVING filtre les lignes du jeu de résultats avec une vérification conditionnelle booléenne, tout comme la clause WHERE, sauf qu'il filtre les lignes formées par la clause GROUP BY et/ou les fonctions d'agrégation.
AYANT des faits saillants :
- La clause HAVING peut référencer les colonnes nommées dans les fonctions d'agrégation (même celles qui ne sont pas groupées) en plus des colonnes GROUP BY.
- HAVING est responsable de l'élimination des lignes après l'application des fonctions d'agrégation ou du regroupement.
- Vous pouvez référencer des colonnes non agrégées dans la clause HAVING bien que cela soit très peu utile.
- Bien que la clause HAVING soit souvent utilisée conjointement avec la clause GROUP BY, vous pouvez l'utiliser seule. Les résultats de la requête sont regroupés dans un seul groupe de ces colonnes dans les fonctions d'agrégation uniquement.
Consultez la section Clause officielle PostgreSQL HAVING pour une couverture détaillée.
ORDER BY - Une mesure de l'ordre hors du hasard
Est une clause facultative.
Utilisez ORDER BY lorsque vous avez besoin d'un ordre spécifique. Sinon, la base de données peut (et retournera) des résultats dans n'importe quel ordre arbitraire.
Même si les résultats semblent être dans un semblant d'ordre, cela n'est pas garanti.
Ne soyez pas dupe. Utilisez ORDRE PAR.
Il existe deux modèles de commande disponibles. Ordre ASC (croissant) ou DESC (décroissant), ASC étant la valeur par défaut.
Si votre ensemble de résultats doit inclure des valeurs NULL, celles-ci peuvent également être utilisées dans le classement comme suit :spécifier NULLS LAST les fait trier (NULLs) après les non-NULL alors que demander NULLS FIRST est l'inverse.
Trier par faits saillants :
- Les expressions de tri sont celles qui seraient autorisées dans la liste SELECT de la requête.
- PostgreSQL vous permet de ORDER BY les colonnes non présentes dans la clause SELECT, contrairement à certains dialectes SQL.
- Les résultats de la requête sont capricieux et il n'est pas garanti qu'ils ressemblent à un modèle ou à un ordre, sauf si une clause ORDER BY est utilisée.
- ORDER BY et la clause LIMIT (voir la section suivante) sont excellentes combinées pour déterminer un 'Top ' ensemble de résultats de lignes. (par exemple, 5 jours de ventes les plus élevées, 5 paires de chaussures les moins vendues, meilleur vendeur ce trimestre)
- Vous pouvez trier les résultats par numéro de position de colonne dans la liste SELECT, mais le nombre spécifié ne doit pas être supérieur au nombre d'éléments dans ladite liste de clauses SELECT. En d'autres termes, si la clause SELECT n'a que 2 éléments, alors ORDER BY 3 produira une erreur.
- Chaque expression individuelle n'est triée que par son option listée. (par exemple, ORDER BY col_1 DESC, col_2 DESC n'est pas identique à ORDER BY col_1, col_2 DESC)
Consultez la section Clause officielle PostgreSQL ORDER BY pour une couverture détaillée.
Téléchargez le livre blanc aujourd'hui PostgreSQL Management &Automation with ClusterControlDécouvrez ce que vous devez savoir pour déployer, surveiller, gérer et faire évoluer PostgreSQLTélécharger le livre blancLIMIT - Récupérer un nombre spécifique de lignes à partir des résultats de la requête
LIMIT est une clause facultative.
LIMIT se compose en fait de 2 sous-clauses, OFFSET étant la seconde d'entre elles.
Si une valeur est fournie pour la partie OFFSET de la clause, les lignes de l'ensemble de résultats sont renvoyées après en sautant ce nombre de lignes.
Une section importante dans la documentation à noter :
"Le planificateur de requêtes prend en compte LIMIT lors de la génération d'un plan de requête, il est donc très probable que vous obteniez différents plans (produisant différents ordres de lignes) en fonction de ce que vous utilisez pour LIMIT et OFFSET. Ainsi, en utilisant différentes valeurs LIMIT/OFFSET pour sélectionner différents les sous-ensembles d'un résultat de requête donneront des résultats incohérents à moins que vous n'appliquiez un ordre prévisible des résultats avec ORDER BY. Ce n'est pas un bogue ; c'est une conséquence inhérente au fait que SQL ne promet pas de fournir les résultats d'une requête dans un ordre particulier sauf si ORDER BY est utilisé pour contraindre l'ordre."
LIMIT points saillants :
- LIMIT peut éventuellement renvoyer moins de lignes que le nombre défini si la requête elle-même produit moins de lignes dans le jeu de résultats. En d'autres termes, cela n'aurait aucun impact sur le nombre de lignes renvoyées.
- La syntaxe LIMIT ALL est acceptable et a le même effet que de ne pas inclure de clause LIMIT du tout.
- Bien que 'x' nombre de lignes soient ignorées en raison d'une clause OFFSET, il ne s'agit pas d'une 'solution de contournement ' pour tout gain de performances, car ils sont toujours calculés pour le plan de requête dans le serveur.
- OFFSET 0 équivaut à ne pas inclure de clause OFFSET du tout.
Consultez la section Clause LIMIT officielle de PostgreSQL pour une couverture détaillée.
L'interprétation de PostgreSQL des principales clauses SQL est la sienne. Quelle que soit la manière dont PostgreSQL choisit de les implémenter ou non, ils sont fondamentaux pour les requêtes SQL et la connaissance de leurs caractéristiques individuelles (et nuances) ne peut que profiter aux utilisateurs à l'avenir.
Bien que des volumes d'articles, de livres, de documentation et de blogs aient été écrits sur chacune de ces clauses, j'espère que vous trouverez cet aperçu de haut niveau digeste et informatif.
Merci d'avoir lu.