SELECT

Nom

SELECT -- récupère des lignes d'une table ou d'une vue

Synopsis

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS nom_d_affichage ] [, ...]
    [ FROM éléments_from [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
    [ ORDER BY expression [ ASC |
DESC | USING opérateur ] [, ...] ]
    [ LIMIT { nombre | ALL } ]
    [ OFFSET début ]
    [ FOR UPDATE [ OF nom_table [,
...] ] ]

où éléments_from fait partie de:

    [ ONLY ] nom_table [ * ] [ [
AS ] alias [ ( alias_colonne [, ...] ) ] ]
    ( select ) [ AS ] alias [ ( alias_colonne [, ...] ) ]
    nom_fonction ( [ argument [, ...] ] ) [ AS ] alias [ ( alias_colonne [, ...] | définition_colonne [, ...] ) ]
    nom_fonction ( [ argument [, ...] ] ) AS ( définition_colonne [, ...] )
    éléments_from [ NATURAL ]
type_jointure éléments_from [ ON condition_jointure | USING ( colonne_jointure [, ...] ) ]

Description

SELECT récupère des lignes à partir d'une ou plusieurs tables. Le traitement général de SELECT est le suivant :

  1. Tous les éléments de la liste FROM sont calculés. (Chaque élément dans la liste FROM est une table réelle ou virtuelle.) Si plus d'un élément est spécifié dans la liste FROM, ils sont joints ensemble. (Voir Clause FROM ci-dessous.)

  2. Si la clause WHERE est spécifiée, toutes les lignes qui ne satisfont pas les conditions sont éliminées de l'affichage. (Voir Clause WHERE ci-dessous.)

  3. Si la clause GROUP BY est spécifiée, l'affichage est divisé en groupes de lignes qui correspondent à une ou plusieurs valeurs. Si la clause HAVING est présente, elle élimine les groupes qui ne satisfont pas la condition donnée. (Voir Clause GROUP BY et Clause HAVING ci-dessous.)

  4. Les lignes en sortie sont traitées en utilisant les expressions de sortie de SELECT pour chaque ligne sélectionnée. (Voir Liste SELECT ci-dessous.)

  5. En utilisant les opérateurs UNION, INTERSECT et EXCEPT, l'affichage de plus d'une instruction SELECT peut être combiné pour former un ensemble de résultats. L'opérateur UNION renvoie toutes les lignes qui sont dans un ou plusieurs ensembles de résultats. L'opérateur INTERSECT renvoie toutes les lignes qui sont dans les deux ensembles de résultats. L'opérateur EXCEPT renvoie les lignes qui sont présentes dans le premier ensemble de résultats mais pas dans le deuxième. Dans les trois cas, les lignes dupliquées sont éliminées sauf si ALL est spécifié. (Voir Clause UNION, Clause INTERSECT et Clause EXCEPT ci-dessous.)

  6. Si la clause ORDER BY est spécifiée, les lignes renvoyées sont triées dans l'ordre spécifié. Si ORDER BY n'est pas indiqué, les lignes sont renvoyées dans l'ordre que le système trouve le plus rapide à fournir. (Voir Clause ORDER BY ci-dessous.)

  7. DISTINCT élimine les lignes dupliquées du résultat. DISTINCT ON élimine les lignes qui correspondent à toutes les expressions données. ALL (la valeur par défaut) renvoie toutes les lignes candidates, y compris les lignes dupliquées. (Voir Clause DISTINCT ci-dessous.)

  8. Si les clauses LIMIT ou OFFSET sont spécifiées, l'instruction SELECT ne renvoie qu'un sous-ensemble de lignes de résultats. (Voir Clause LIMIT ci-dessous.)

  9. La clause FOR UPDATE fait que l'instruction verrouille les lignes sélectionnées contre les mises à jour concurrentes. (Voir Clause FOR UPDATE ci-dessous.)

Vous devez avoir le droit SELECT sur une table pour lire ses valeurs. L'utilisation de FOR UPDATE requiert de plus le droit UPDATE.

Paramètres

Clause FROM

La clause FROM spécifie une ou plusieurs tables source pour SELECT. Si plusieurs sources sont spécifiées, le résultat est un produit cartésien (jointure croisée) de toutes les sources. Mais habituellement, des conditions de qualification sont ajoutées pour restreindre les lignes renvoyées à un petit sous-ensemble de produit cartésien.

La clause FROM peut contenir les éléments suivants :

nom_table

Le nom (pouvant être qualifié du nom du schéma) d'une table existante ou d'une vue. Si ONLY est spécifié, seule cette table est parcourue. Si ONLY n'est pas spécifié, la table et toutes ses descendantes (si elles existent) sont parcourues. * peut être ajouté au nom de la table pour indiquer que les tables descendantes doivent être parcourues mais, dans la version actuelle, c'est le comportement par défaut. (Dans les versions précédant la 7.1, ONLY était le comportement par défaut.) Le comportement par défaut peut être modifié en changeant l'option de configuration sql_inheritance.

alias

Un nom de substitution pour l'élément FROM contenant l'alias. Un alias est utilisé par brièveté ou pour éliminer toute ambiguïté pour les jointures où la même table est parcourue plusieurs fois. Quand un alias est fourni, il cache complètement le nom réel de la table ou fonction  ; par exemple, avec FROM foo AS f, le reste du SELECT doit faire référence à cet élément de FROM par f et non pas par foo. Si un alias est donné, une liste d'alias de colonnes peut aussi être saisi pour fournir des noms de substitution pour une ou plusieurs colonnes de la table.

select

Un sous-SELECT peut apparaître dans la clause FROM. Ceci agit comme si sa sortie était transformée en une table temporaire pour la durée de cette seule commande SELECT. Notez que le sous-SELECT doit être entouré par des parenthèses et qu'un alias doit être fourni pour le sous-SELECT.

nom_fonction

Des appels de fonctions peuvent apparaître dans la clause FROM. (Ceci est particulièrement utile pour les fonctions renvoyant des ensembles de résultats mais toute fonction peut être utilisée.) Ceci agit comme si la sortie était transformée en une table temporaire pour la durée de cette seule commande SELECT. Un alias peut aussi être utilisé. Si un alias est donné, une liste d'alias de colonnes peut être ajoutée pour fournir des noms de substitution pour un ou plusieurs attributs du type composé de retour de la fonction. Si la fonction a été définie comme renvoyant le type de données record, alors un alias ou un mot clé AS doit être présent, suivi par une liste de définitions de colonnes de la forme ( nom_colonne type_données [, ... ] ). La liste de définitions de colonnes doit correspondre au nombre réel et aux types réels des colonnes renvoyées par la fonction.

type_jointure

Fait partie de

  • [ INNER ] JOIN

  • LEFT [ OUTER ] JOIN

  • RIGHT [ OUTER ] JOIN

  • FULL [ OUTER ] JOIN

  • CROSS JOIN

Pour les types de jointures INNER et OUTER, une condition de jointure doit être spécifiée, parmi NATURAL, ON condition_jointure ou USING (colonne_jointure [, ...]). Voir ci-dessous pour la signification. Pour CROSS JOIN, aucune de ces clauses ne doit apparaître.

Une clause JOIN combine deux éléments FROM. Utilisez les parenthèses si nécessaire pour déterminer l'ordre d'imbrication. En l'absence de parenthèses, les JOIN sont imbriqués de gauche à droite. Dans tous les cas, JOIN est plus prioritaire que les virgules séparant les éléments FROM.

CROSS JOIN et INNER JOIN produisent un simple produit cartésien, le même résultat que vous obtenez à partir de la liste de deux éléments au niveau haut du FROM, mais restreint par la condition de jointure (si elle existe). CROSS JOIN est équivalent à INNER JOIN ON (TRUE), c'est-à-dire qu'aucune ligne n'est supprimée par qualification. Ces types de jointure sont juste une aide à la notation car ils ne font rien de plus qu'un simple FROM et WHERE.

LEFT OUTER JOIN renvoie toutes les lignes dans le produit cartésien qualifié (c'est-à-dire toutes les lignes combinées qui réussissent la condition de jointure), plus une copie de chaque ligne dans le côté gauche de la table pour laquelle il n'y a pas de côté droit qui a réussi la condition de jointure. Cette ligne côté gauche est étendue à la largeur complète de la table jointe par insertion de valeurs NULL pour les colonnes côté droit. Notez que seule la condition de la clause JOIN est utilisée pour décider des lignes qui correspondent. Les conditions externes sont appliquées après coup.

Au contraire, RIGHT OUTER JOIN renvoie toutes les lignes jointes plus une ligne pour chaque ligne côté droit sans correspondance (complétée par des NULL pour le côté gauche). Ceci est une simple aide à la notation car vous pourriez la convertir en LEFT en inversant les entrées gauche et droite.

FULL OUTER JOIN renvoie toutes les lignes jointes, plus chaque ligne gauche sans correspondance (étendue par des NULL à droite), plus chaque ligne droite sans correspondance (étendue par des NULL à gauche).

ON condition_jointure

condition_jointure est une expression qui renvoie une valeur de type boolean (similaire à une clause WHERE) qui spécifie quelles lignes d'une jointure doivent correspondre.

USING (colonne_jointure [, ...])

Une clause de la forme USING ( a, b, ... ) est un raccourci pour ON left_table.a = right_table.a AND left_table.b = right_table.b .... De plus, USING implique que seule une des paires de colonnes équivalentes est inclue dans la sortie de la jointure, pas les deux.

NATURAL

NATURAL est un raccourci pour une liste USING qui mentionne toutes les colonnes dans les deux tables qui ont le même nom.

Clause WHERE

La clause WHERE optionnelle a la forme générale

WHERE condition

condition est une expression qui s'évalue en un résultat de type boolean. Toute ligne ne satisfaisant pas cette condition est éliminée de la sortie. Une ligne satisfait la condition si elle renvoie vrai quand les valeurs réelles de la ligne sont substituées à toute référence de variable.

Clause GROUP BY

La clause GROUP BY optionnelle a la forme générale

GROUP BY expression [, ...]

GROUP BY condense en une seule ligne toutes les lignes sélectionnées qui partagent les mêmes valeurs pour les expressions groupées. expression peut être un nom de colonne en entrée, ou le nom ou le nombre ordinal d'une colonne en sortie (élément de la liste SELECT), ou une expression arbitraire formée par des valeurs de colonnes en entrée. Dans le cas d'une ambiguïté, un nom GROUP BY est interprété comme un nom de colonne en entrée plutôt qu'un nom de colonne en sortie.

Les fonctions d'agrégat, si elles sont utilisées, sont calculées pour toutes les lignes composant chaque groupe, produisant une valeur séparée pour chaque groupe (alors que sans GROUP BY, un agrégat produit une valeur unique calculée avec toutes les lignes sélectionnées). Quand GROUP BY est présent, il n'est pas valide que les expressions de liste SELECT fassent référence aux colonnes non groupées sauf à l'intérieur de fonctions d'agrégat car il y aurait plus d'une valeur possible à renvoyer pour une colonne non groupée.

Clause HAVING

La clause HAVING optionnelle a la forme générale

HAVING condition

condition est identique à celle spécifiée pour la clause WHERE.

HAVING élimine les lignes groupées qui ne satisfont pas à la condition. HAVING est différent de WHERE : WHERE filtre les lignes individuelles avant l'application de GROUP BY alors que HAVING filtre les lignes groupées créées par GROUP BY. Chaque colonne référencée dans condition doit référencer sans ambiguïté une colonne groupée, sauf si la référence apparaît dans une fonction d'agrégat.

Liste SELECT

La liste SELECT (entre les mots clés SELECT et FROM) spécifie les expressions qui forment les lignes en sortie de l'instruction SELECT. Les expressions peuvent faire (et en général font) référence aux colonnes traitées dans la clause FROM. En utilisant la clause AS nom_sortie, un autre nom peut être indiqué pour une colonne en sortie. Ce nom est principalement utilisé pour nommer la colonne à l'affichage. Il peut aussi être utilisé pour référencer la valeur de la colonne dans les clauses ORDER BY et GROUP BY, mais pas dans les clauses WHERE ou HAVING ; là, vous devez écrire les expressions à la place.

Au lieu d'une expression, on peut utiliser * dans la liste de sortie comme raccourci pour toutes les colonnes des lignes sélectionnées. De plus, vous pouvez écrire nom_table.* comme raccourci pour toutes les colonnes provenant de cette table.

Clause UNION

La clause UNION a la forme générale :

instruction_select UNION [ ALL ]
instruction_select

instruction_select est toute instruction SELECT sans clause ORDER BY, LIMIT ou FOR UPDATE. (ORDER BY et LIMIT peuvent être attachés à une sous-expression si elle est englobée dans des parenthèses. Sans parenthèses, ces clauses s'appliquent au résultat de l'UNION, et non pas à son expression côté droit.)

L'opérateur UNION calcule l'union ensembliste des lignes renvoyées par les instructions SELECT impliquées. Une ligne est dans l'union de deux ensembles de résultats si elle apparaît dans au moins un des ensembles de résultats. Les deux instructions SELECT qui représentent les opérandes directs de l'UNION doivent produire le même nombre de colonnes et les colonnes correspondantes doivent être d'un type de données compatible.

Le résultat de UNION ne doit pas contenir de lignes dupliquées sauf si l'option ALL est spécifiée. ALL empêche l'élimination des lignes dupliquées. (Du coup, UNION ALL est significativement plus rapide qu'UNION ; utilisez ALL quand vous le pouvez.)

Plusieurs opérateurs UNION dans la même instruction SELECT sont évalués de gauche à droite sauf si c'est indiqué autrement par des parenthèses.

Actuellement, FOR UPDATE ne peut pas être spécifié pour un résultat UNION ou pour toute entrée d'un UNION.

Clause INTERSECT

La clause INTERSECT a cette forme générale :

instruction_select INTERSECT [ ALL ] instruction_select

instruction_select est toute instruction SELECT sans clause ORDER BY, LIMIT ou FOR UPDATE.

L'opérateur INTERSECT calcule l'intersection des lignes renvoyées par les instructions SELECT impliquées. Une ligne est dans l'intersection des deux ensembles de résultats si elle apparaît dans chacun des deux ensembles.

Le résultat d'INTERSECT ne contient pas de lignes dupliquées sauf si l'option ALL est spécifiée. Avec ALL, une ligne qui a m lignes dupliquées dans la table gauche et n lignes dupliquées dans la table droite apparaît min(m,n) fois dans l'ensemble de résultats.

Plusieurs INTERSECT dans la même instruction SELECT sont évalués de gauche à droite sauf si des parenthèses dictent le contraire. INTERSECT est plus prioritaire que UNION. C'est-à-dire que A UNION B INTERSECT C est lu comme A UNION (B INTERSECT C).

Actuellement, FOR UPDATE ne peut pas être spécifié pour un résultat d'INTERSECT ou pour une entrée d'INTERSECT.

Clause EXCEPT

La clause EXCEPT a cette forme générale :

instruction_select EXCEPT [ ALL ]
instruction_select

instruction_select est toute instruction SELECT sans clause ORDER BY, LIMIT ou FOR UPDATE.

L'opérateur EXCEPT calcule l'ensemble de lignes qui sont dans le résultat de l'instruction SELECT de gauche mais pas dans le résultat de celle de droite.

Le résultat de EXCEPT ne contient aucune ligne dupliquée sauf si l'option ALL est spécifiée. Avec ALL, une ligne qui a m dupliquées dans la table gauche et n dupliquées dans la table droite apparaît max(m-n,0) fois dans l'ensemble de résultat.

Plusieurs opérateurs EXCEPT dans la même instruction SELECT sont évalués de gauche à droite sauf si des parenthèses dictent le contraire. EXCEPT a la même priorité qu'UNION.

Actuellement, FOR UPDATE ne peut pas être spécifié dans un résultat EXCEPT ou pour une entrée d'un EXCEPT.

Clause ORDER BY

La clause optionnelle ORDER BY a cette forme générale :

ORDER BY expression [ ASC | DESC |
USING opérateur ] [, ...]

expression peut être le nom ou le numéro ordinal d'une colonne en sortie (élément de la liste SELECT) ou il peut être une expression quelconque formée à partir des valeurs des colonnes en entrée.

La clause ORDER BY fait que les lignes de résultat sont triées suivant les expressions données. Si deux lignes sont identiques suivant l'expression la plus à gauche, elles sont comparées avec l'expression suivante et ainsi de suite. Si elles sont identiques pour toutes les expressions de tri, elles sont renvoyées dans un ordre dépendant de l'implémentation.

Le numéro ordinal fait référence à la position ordinale (de gauche à droite) de la colonne de résultat. Cette fonctionnalité rend possible de définir un ordre sur la base d'une colonne qui n'a pas un nom unique. Ceci n'est jamais absolument nécessaire parce qu'il est toujours possible d'affecter un nom à une colonne résultat en utilisant la clause AS.

Il est aussi possible d'utiliser des expressions quelconques dans la clause ORDER BY, incluant des colonnes qui n'apparaissent pas dans la liste de résultat du SELECT. Du coup, l'instruction suivante est valide :

SELECT nom FROM distributeurs ORDER BY code;

Une limitation de cette fonctionnalité est que la clause ORDER BY s'appliquant au résultat d'une clause UNION, INTERSECT ou EXCEPT peut seulement spécifier un nom ou numéro de colonne en sortie, pas une expression.

Si une expression ORDER BY est un simple nom qui correspond à la fois à un nom de colonne résultat et à un nom de colonne en entrée, ORDER BY l'interprète comme le nom de la colonne résultat. Ceci est le contraire du choix que GROUP BY fait dans la même situation. Cette incohérence est nécessaire pour être compatible avec le standard SQL.

Optionnellement, vous pourriez ajouter le mot clé ASC (ascendant) ou DESC (descendant) après toute expression de la clause ORDER BY. Sans indication, ASC est la valeur supposée par défaut. Autrement, un nom d'opérateur d'ordre spécifique peut être fourni dans la clause USING. ASC est habituellement équivalent à USING < et DESC est habituellement équivalent à USING >. (Mais le créateur d'un type de données défini par l'utilisateur peut définir à sa guise le tri par défaut et il pourrait correspondre à des opérateurs de nom différent.)

La valeur NULL est triée plus haut que toute autre valeur. En d'autres termes, avec un ordre de tri ascendant, les valeurs NULL sont triées à la fin et avec un ordre de tri descendant, elles sont triées au début.

Les données de chaînes de caractères sont triées suivant l'ordre spécifique à la locale, ordre établi au moment de la création du groupe de bases de données.

Clause DISTINCT

Si DISTINCT est spécifié, toutes les lignes dupliquées sont supprimées de l'ensemble de résultat (une ligne est conservée pour chaque groupe de lignes dupliquées). ALL spécifie le contraire : toutes les lignes sont conservées ; ceci est la valeur par défaut.

DISTINCT ON ( expression [, ...] ) conserve seulement la première ligne de chaque ensemble de lignes où les expressions sont évaluées comme identiques. Les expressions DISTINCT ON sont interprétées en utilisant les mêmes règles que pour ORDER BY (voir ci-dessus). Notez que la << première ligne >> de chaque ensemble n'est pas prévisible sauf si ORDER BY est utilisé pour s'assurer que la ligne désirée apparaît en premier. Par exemple,

  SELECT DISTINCT ON (emplacement) emplacement, heure, rapport
  FROM rapports_meteo
  ORDER BY emplacement, heure DESC;

récupère le rapport météo le plus récent pour chaque emplacement. Mais si nous n'avions pas utilisé ORDER BY pour forcer l'ordre descendant des valeurs heure pour chaque emplacement, nous aurions obtenu un rapport à partir d'une heure non prévisible pour chaque emplacement.

Le(s) expression(s) DISTINCT ON doi(ven)t correspondre à l'ordre des expression ORDER BY. La clause ORDER BY contient normalement des expressions supplémentaires qui déterminent la précédence désirée des lignes à l'intérieur de chaque groupe DISTINCT ON.

Clause LIMIT

La clause LIMIT est constituée de deux sous-clauses indépendantes :

LIMIT { nombre | ALL }
OFFSET début

nombre spécifie le nombre maximum de lignes à renvoyer alors que début spécifie le nombre de lignes à passer avant de commencer à renvoyer des lignes. Quand les deux sont spécifiés, début lignes sont passées avant de commencer à compter les nombre lignes à renvoyer.

Lors de l'utilisation de LIMIT, utiliser la clause ORDER BY est une bonne idée pour contraindre les lignes de résultat en un ordre unique. Sinon, vous obtenez un sous-ensemble non prévisible de lignes de la requête — vous pouvez demander les lignes 10 à 20 mais de la 10 à la 20 dans quel ordre ? Vous ne savez pas l'ordre tant que vous ne le spécifiez pas avec ORDER BY.

Le planificateur de requêtes prend LIMIT en compte lors de la génération d'un plan de requêtes, donc vous avez beaucoup de chances d'obtenir des plans différents (récupération d'ordre de lignes différents) suivant ce que vous utilisez pour LIMIT et OFFSET. Du coup, l'utilisation de valeurs différentes pour LIMIT/OFFSET pour sélectionner des sous-ensembles d'un résultat de requête donne éventuellement des résultats incohérents sauf si vous forcez un ordre de résultat prévisible avec ORDER BY. Ceci n'est pas un bogue ; c'est une conséquence inhérente au fait que SQL ne promet pas de délivrer les résultats d'une requête dans un ordre particulier sauf si ORDER BY est utilisé pour forcer cet ordre.

Clause FOR UPDATE

La clause FOR UPDATE a cette forme :

FOR UPDATE [ OF nom_table [, ...] ]

FOR UPDATE fait que les lignes récupérées par l'instruction SELECT sont verrouillées pour modification. Ceci les empêche d'être modifiées ou supprimées par les autres transactions jusqu'à la fin de la transaction en cours. C'est-à-dire que les autres transactions tentant des UPDATE, DELETE ou SELECT FOR UPDATE de ces lignes sont bloquées jusqu'à ce que la transaction en cours se termine. De plus, si un UPDATE, DELETE ou SELECT FOR UPDATE à partir d'une autre transaction a déjà verrouillé une ligne ou un ensemble de lignes, SELECT FOR UPDATE attend la fin de l'autre transaction puis verrouille et renvoie la ligne modifiée (ou aucune ligne si elle a été supprimée). Pour plus d'informations, voir Chapitre 12.

Si des tables spécifiques sont nommées dans FOR UPDATE, alors seules les lignes provenant de ces tables sont verrouillées  toute autre table utilisée dans le SELECT est simplement lue comme d'habitude.

FOR UPDATE ne peut pas être utilisé dans les contextes où les lignes renvoyées ne peuvent pas être clairement identifiées avec des lignes d'une table individuelle ; par exemple, elle ne peut pas être utilisée avec des agrégats.

FOR UPDATE peut apparaître avant LIMIT pour la compatibilité avec les versions de PostgreSQL antérieures à la 7.3. Il s'exécute néanmoins après LIMIT, et c'est donc l'emplacement recommandée pour l'écrire.

Attention

Évitez de verrouiller une ligne, puis de la modifier à l'intérieur d'un nouveau point de sauvegarde ou dans un bloc d'exception PL/pgSQL. Une annulation suivante causerait la perte du verrou. Par exemple :

BEGIN;
SELECT * FROM ma_table WHERE cle = 1 FOR UPDATE;
SAVEPOINT s;
UPDATE ma_table SET ... WHERE cle = 1;
ROLLBACK TO s;

Après le ROLLBACK, la ligne est réellement déverrouillée, au lieu d'être renvoyée dans son état avant le point de sauvegarde (donc verrouillée et non modifiée). Ce hasard survient si une ligne verrouillée dans la transaction en cours est mise à jour ou supprimée : l'état de verrouillage précédent est oublié. Si la transaction est annulée par la suite, à un état entre la commande initiale de verrouillage et la modification, la ligne n'apparaîtra plus du tout verrouillée. C'est un problème de l'implémentation qui sera adressé dans une prochaine version de PostgreSQL.

Attention

Il est possible pour une commande SELECT utilisant les deux clauses LIMIT et FOR UPDATE de renvoyer moins de lignes que celles spécifiées par LIMIT. Ceci est dû au fait que LIMIT sélectionne un nombre de lignes mais pourrait ensuite bloquer lors de la demande d'un verrou FOR UPDATE. Une fois que le SELECT est débloqué, la qualification de la requête pourrait ne pas être rencontrée et la ligne ne serait pas renvoyée par le SELECT.

Exemples

Pour joindre la table films avec la table distributeurs :

SELECT f.titre, f.did, d.nom, f.date_prod, f.genre
    FROM distributeurs d, films f
    WHERE f.did = d.did

       titre       | did |     nom      | date_prod  |   genre
-------------------+-----+--------------+------------+------------
 The Third Man     | 101 | British Lion | 1949-12-23 | Drame
 The African Queen | 101 | British Lion | 1951-08-11 | Romantique
 ...

Pour additionner la colonne longueur de tous les films, grouper les résultats par genre :

SELECT genre, sum(longueur) AS total FROM films GROUP BY genre;

   genre    | total
------------+-------
 Action     | 07:34
 Comédie    | 02:58
 Drame      | 14:28
 Musical    | 06:42
 Romantique | 04:38

Pour additionner la colonne longueur de tous les films, grouper les résultats par genre et afficher les groupes dont les totaux font moins de cinq heures :

SELECT genre, sum(longueur) AS total
    FROM films
    GROUP BY genre
    HAVING sum(longueur) < interval '5 hours';

   genre    | total
------------+-------
 Comedie    | 02:58
 Romantique | 04:38

Les deux exemples suivants sont des façons identiques de trier les résultats individuels suivant le contenu de la deuxième colonne (nom) :

SELECT * FROM distributeurs ORDER BY nom;
SELECT * FROM distributeurs ORDER BY 2;

 did |       nom
-----+------------------
 109 | 20th Century Fox
 110 | Bavaria Atelier
 101 | British Lion
 107 | Columbia
 102 | Jean Luc Godard
 113 | Luso films
 104 | Mosfilm
 103 | Paramount
 106 | Toho
 105 | United Artists
 111 | Walt Disney
 112 | Warner Bros.
 108 | Westward

Le prochain exemple montre comment obtenir l'union des tables distributeurs et acteurs, restreignant les résultats à ceux commençant avec la lettre W dans chaque table. Seules les lignes distinctes sont voulues, du coup le mot clé ALL est omis.

distributeurs:               acteurs:
 did |     nom               id |     nom
-----+--------------        ----+----------------
 108 | Westward               1 | Woody Allen
 111 | Walt Disney            2 | Warren Beatty
 112 | Warner Bros.           3 | Walter Matthau
 ...                         ...

SELECT distributeurs.nom
    FROM distributeurs
    WHERE distributeurs.nom LIKE 'W%'
UNION
SELECT actors.nom
    FROM acteurs
    WHERE acteurs.nom LIKE 'W%';

      nom
----------------
 Walt Disney
 Walter Matthau
 Warner Bros.
 Warren Beatty
 Westward
 Woody Allen

Cet exemple montre comment utiliser une fonction dans la clause FROM, à la fois avec et sans une liste de définition de colonnes :

CREATE FUNCTION distributeurs(int) RETURNS SETOF distributeurs AS $$
    SELECT * FROM distributeurs WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributeurs(111);
 did |    name
-----+-------------
 111 | Walt Disney

CREATE FUNCTION distributeurs_2(int) RETURNS SETOF record AS $$
    SELECT * FROM distributeurs WHERE did = $1;
$$ LANGUAGE SQL;

SELECT * FROM distributeurs_2(111) AS (f1 int, f2 text);
 f1  |     f2
-----+-------------
 111 | Walt Disney

Compatibilité

Bien sûr, l'instruction SELECT est compatible avec le standard SQL. Mais il y a des extensions et quelques fonctionnalités manquantes.

Clauses FROM omises

PostgreSQL vous permet d'omettre la clause FROM. Cela permet par exemple de calculer le résultat d'expressions simples :

SELECT 2+2;

 ?column?
----------
        4

D'autre bases de données SQL ne le permettent pas, sauf en introduisant une table d'une seule ligne à partir de laquelle la commande SELECT s'exécute.

Une utilisation moins évidente est de raccourcir un SELECT normal à partir des tables :

SELECT distributeurs.* WHERE distributeurs.name = 'Westward';

 did |   name
-----+----------
 108 | Westward

Ceci fonctionne parce qu'un élément FROM implicite est ajouté pour chaque table référencée dans d'autres parties de l'instruction SELECT mais non mentionnée dans FROM.

Bien qu'il s'agisse d'un raccourci agréable, sa mauvaise utilisation est facile. Par exemple, la commande

SELECT distributeurs.* FROM distributeurs d;

est probablement une erreur ; il est probable que l'utilisateur souhaitait

SELECT d.* FROM distributeurs d;

plutôt que la jointure sans contrainte

SELECT distributeurs.* FROM distributeurs d, distributeurs distributeurs;

qu'il obtient réellement. Pour aider à la détection de ce type d'erreur, PostgreSQL avertit de l'utilisation de la fonctionnalité du FROM implicite dans une instruction SELECT qui contient aussi une clause FROM explicite. De plus, il est possible de désactiver la fonctionnalité du FROM implicite en initialisant le paramètre add_missing_from à false.

Mot clé AS

Dans le SQL standard, le mot clé optionnel AS est seulement du bruit et peut être omis sans affecter la signification. L'analyseur PostgreSQL requiert ce mot clé lors du renommage des colonnes en sortie parce que les fonctionnalités d'extension du type créent des ambiguïtés en son absence. AS est néanmoins optionnel pour les éléments FROM.

Espace logique disponible pour GROUP BY et ORDER BY

Dans le standard SQL-92, une clause ORDER BY peut seulement utiliser des noms ou des numéros de colonnes alors qu'une clause GROUP BY peut seulement utiliser des expressions basées sur les noms de colonne en entrée. PostgreSQL étend chacune de ces clauses pour permettre aussi un autre choix (mais il utilise l'interprétation du standard s'il y a ambiguïté). PostgreSQL autorise aussi les deux clauses à spécifier des expressions quelconques. Notez que les noms apparaissant dans une expression sont toujours pris en tant que noms des colonnes en entrée, et non pas en tant que noms des colonnes du résultat.

SQL:1999 utilise une définition légèrement différente qui n'est pas totalement compatible avec SQL-92. Néanmoins, dans la plupart des cas, PostgreSQL interpréte une expression ORDER BY ou GROUP BY de la même façon que ce que fait SQL:1999.

Clauses non standard

Les clauses DISTINCT ON, LIMIT et OFFSET ne sont pas définies dans le standard SQL.