SELECT

Name

SELECT  --  permet de retrouver les lignes d'une table ou d'une vue.

Synopsis

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS output_name ] [, ...]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ FOR UPDATE [ OF tablename [, ...] ] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start ]

where from_item can be:

[ ONLY ] table_name [ * ]
    [ [ AS ] alias [ ( column_alias_list ) ] ]
|
( select )
    [ AS ] alias [ ( column_alias_list ) ]
|
from_item [ NATURAL ] join_type from_item
    [ ON join_condition | USING ( join_column_list ) ]
  

Entrées

expression

Nom d'une colonne de table ou d'une expression.

output_name

Spécifie un autre nom pour une colonne en utiliant la clause AS. Ce nom est utilisé d'abord pour labelliser la colonne pour l'affichage. Il peut aussi être utilisé en référence à la valeur de la colonne dans les clauses ORDER BY et GROUP BY. Mais le output_name ne peut être utilisé dans les clauses WHERE ou HAVING.

from_item

Une référence de table, sous-sélection, ou une clause JOIN. Voir plus bas pour les détails.

condition

Une expression booléenne donnant un résultat vrai ou faux. Voir la description des clauses WHERE et HAVING plus bas.

select

Une instruction de sélection avec toutes les fonctionnalités sauf les clauses ORDER BY, FOR UPDATE, et LIMIT.

Les items FROM peuvent contenir :

table_name

Le nom d'une table ou d'une vue existante. Si ONLY est spécifié, seule cette table est parcourue. Si ONLY n'est pas spécifié, la table et toutes ses tables descendantes (si c'est la cas) sont parcourue. * peut être attendu comme nom de table pour indiquer que les tables descendantes seront parcourues, mais dans la version actuelle, c'est le comportement par défaut. (Dans les versions antérieures à la 7.1, ONLY était le comportement par défaut).

alias

Un nom de substitution pour le table_name précédent. Un alias est utilisé pour la concision ou pour éliminer toute ambiguïté sur les auto-jointures (où la même table est parcourue plusieurs fois). Si un alias est écrit, une liste d'alias de colonnes peut aussi être écrite pour fournir des noms de substitution pour une ou plusieurs colonnes de la table.

select

Une sous-sélection peut apparaître dans la clause FROM. Ceci fait que quoique sa sortie sera créée comme une table temporaire pour la durée de la commande SELECT. Notez que la sous-sélection doit être entourée de parenthèses, et un alias doit être fourni pour elle.

join_type

Une des [ INNER ] JOIN, LEFT [ OUTER ] JOIN, RIGHT [ OUTER ] JOIN, FULL [ OUTER ] JOIN, ou CROSS JOIN. Pour les types de jointure INNER et OUTER, exactement une des NATURAL, ON join_condition, ou USING ( join_column_list ) doit apparaître. Pour CROSS JOIN, aucuns de ces items peut apparaître.

join_condition

Une condition de qualification. C'est similaire à la condition WHERE sauf qu'elle s'applique uniquement aux deux items joints dans la clause JOIN.

join_column_list

Une liste de colonnes USING ( a, b, ... ) est un raccourci pour la condition ON left_table.a = right_table.a AND left_table.b = right_table.b ...

Sorties

Rows

L'ensemble complet des lignes résultant de la spécification de requête.

count

le total des lignes retournées par la requête.

Description

SELECT renvoit les lignes d'une ou plusieurs tables. Les candidates pour la sélection sont des lignes qui satisfont la condition WHERE; si WHERE est omis, toutes les lignes sont candidates. (Voir Clause WHERE.)

Actuellement, les lignes retournées ne sont pas directement les lignes produites par les clauses FROM/WHERE/GROUP BY/HAVING; les sorties lignes sont formées par le calcul des expressions de sortie de SELECT pour chaque ligne. * peut être écrit si la sortie liste a un raccourci pour toutes les colonnes des lignes sélectionnées. On peut également écrire table_name.* comme u raccourci pour les colonnes venant de cette table.

DISTINCT éliminera les lignes dupliquées du résultat. ALL (par défaut) renverra toutes les lignes candidates, incluant les dupliquées.

DISTINCT ON élimine les lignes qui s'apparient sur toutes les expressions spécifiées, gardant seulement la première ligne de chaque ensemble de dupliquées. Les expressions DISTINCT ON sont interprétées en utilisant les mêmes règles que pour ORDER BY; voir plus bas. Notez que la "première ligne" de chaque ensemble est imprévisible à moins que ORDER BY soit utilisé pour s'assurer que les lignes désirées apparaissent en premier. Par exemple,

        SELECT DISTINCT ON (location) location, time, report
        FROM weatherReports
        ORDER BY location, time DESC;
   
retrouve le bulletin météo le plus récent pour chaque endroit. Mais si nous n'avons pas utilisé ORDER BY pour forcer l'ordre descendant des valeurs horaires pour chaque endroit, nous avons obtenu un rapport d'âge inprévisible pour chaque endroit.

La clause GROUP BY permet à un utilisateur de diviser une table en groupes de lignes qui s'apparient sur une ou plusieurs valeurs. (Voir Clause GROUP BY.)

La clause HAVING permet la sélection des seuls groupes de lignes rencontrant une condition spécifiée. (Voir Clause HAVING.)

La clause ORDER BY trie les lignes retournées dans un ordre spécifique. Si ORDER BY n'est pas fourni, les lignes seront retournées dans un ordre déterminé par le système selon ce qu'il trouve de plus facile à produire. (Voir Clause ORDER BY.)

Les requêtes SELECT peuvent être combinées en utilisant les opérateurs UNION, INTERSECT, et EXCEPT Utilisez des parenthèses si nécessaire pour déterminer l'ordre de ces opérateurs.

L'opérateur UNION calcule la collection de lignes retournées par la requête. Les lignes dupliquées sont éliminées sauf si ALL est spécifié. (Voir Clause UNION.)

L'opérateur INTERSECT calcule les lignes communes à deux requêtes. Les lignes dupliquées sont éliminées sauf si ALL est spécifié. (Voir Clause INTERSECT.)

L'opérateur EXCEPT calcule les lignes retournées par la première requête mais pas par la seconde requête. Les lignes dupliquées sont éliminées sauf si ALL est spécifié. (Voir Clause EXCEPT.)

La clause FOR UPDATE permet à l'instruction SELECT d'exécuter le verrouillage exclusifs des lignes sélectionnées.

La clause LIMIT permet à un sous-ensemble de lignes produites par la requête d'être retournées à l'utilisateur. (Voir Clause LIMIT.)

Vous devez avoir les droits de SELECT sur une table pour lire ses valeurs. (Voir les instructions GRANT/REVOKE).

Clause FROM

La clause FROM spécifie une ou plusieurs table sources pour le SELECT. Si plusieurs sources sont spécifiées, le résultat est conceptuellement le produit cartésien de toutes les lignes dans toutes les sources --- mais habituellement les conditions de qualification sont ajoutées pour limiter les lignes retournées à un sous-ensemble du produit cartésien.

Quand FROM est un simple nom de table, il inclut implicitement les lignes des sous-tables (enfant dans l'héritage) de la table. ONLY supprimera les lignes des sous-tables de la table. Avant PostgreSQL 7.1, c'était le résultat par défaut, et l'ajout de sous-tables était réalisé en ajoutant * au nom de la table. Cet ancien comportement est disponible via la commande SET SQL_Inheritance TO OFF;

Un FROM pzut aussi être une sous-sélection entre parenthèses (notez qu'une clause alias est nécessaire pour une sous-sélection !).C'est une fonctionnalité très commode car c'est le seul moyen d'obtenir des niveaux multiples de groupage, agrégation, ou triage dans une seule requête.

Finalement, un FROM peut être une clause JOIN, qui combine deux FROM plus simples. (Utilisez les parenthèses si nécessaire pour déterminer l'ordre).

Une CROSS JOIN ou INNER JOIN est un simple produit cartésien, le même que vous obtenez en listant les deux items au niveau supérieur de FROM. CROSS JOIN est équivalent à INNER JOIN ON (TRUE), aucune ligne n'est supprimée par la qualification. Ces types de jointures ne sont que des conventions de notation, car elles ne font rien que vous pouvez faire avec des FROM et WHERE pleinement qualifiés.

LEFT OUTER JOIN renvoit toutes les lignes dans le produit cartésien qualifié (i.e., toutes les lignes combinées qui passent la condition ON), plus une copie de chaque ligne dans le côté gauche de la table pour lequel il n'y a pas de côté droit qui satisfasse la condition ON. Cette ligne côté gauche est étendue sur la largeur complète de la table jointe en insérant des NULL dans les colonnes côté droit. Notez que seule la propre condition de jointure de ON ou USING est prise en considération lors de la décision de savoir quelles lignes sont appariées. Les conditions ON ou WHERE sont appliquées plus tard.

À l'inverse, RIGHT OUTER JOIN retourne toutes les lignes jointes, plus une ligne pour chaque ligne côté droit non appariée (étendue avec des NULL côté gauche). C'est juste une convention de notation, car vous pouvez la convertir en LEFT OUTER JOIN en basculant les entrées droite et gauche.

FULL OUTER JOIN renvoit toutes les lignes jointes, plus une ligne pour chaque ligne côté gauche non appariée (étendue avec des NULL côté droit), plus une ligne pour chaque ligne côté droit non appariée (étendue avec des NULL côté gauche).

Pour tous les types JOIN sauf CROSS JOIN, vous devez écrire exactement un des ON join_condition, USING ( join_column_list ), ou NATURAL. ON est le cas le plus général : vous pouvez écrire une expression de qualification comprenant les deux tables à joindre. Une liste de colonne USING ( a, b, ... ) est un raccourci pour la condition ON left_table.a = right_table.a AND left_table.b = right_table.b ... Également, USING implique que seule une paire de chaque colonne équivalente sera inclue dans la sortie JOIN, pas les deux. NATURAL est un raccourci pour une liste USING qui mentionne toutes les colonnes nommées de façon similaire dans les tables.

Clause WHERE

La condition optionnelle WHERE a la forme générale :

WHERE boolean_expr
    
boolean_expr peut consister en une expression qui évalue une valeur booléenne. Dans certains cas, cette expression sera :
     expr cond_op expr
    
ou
     log_op expr
    
cond_op peut être un des : =, <, <=, >, >= ou <>, un opérateur conditionnel comme ALL, ANY, IN, LIKE, ou un opérateur défini localement, et log_op peut être un des : AND, OR, NOT. SELECT ignorera toutes les lignes pour lesquelles la condition WHERE ne retourne pas TRUE.

Clause GROUP BY

GROUP BY spécifie une table groupée dérivée de l'application de cette clause :

GROUP BY expression [, ...]
    

GROUP BY condensera en une seule ligne toutes les lignes sélectionnées qui partagent les mêmes valeurs pour les colonnes groupées. Les fonctions agrégat, si elles existent, sont calculées à travers toutes les lignes complétant chaque groupe, produisant une valeur séparée pour chaque groupe (puisque sans GROUP BY, un agrégat produit une seule valeur calculée à travers toutes les lignes sélectionnées). Quand GROUP BY est présent, il n'est pas valide pour l'expression de sortie de SELECT de se référer aux colonnes non groupées sauf dans des fonctions agrégat, car elles auront plus d'une valeur possible à retourner pour une colonne non groupée.

A GROUP BY peut être un nom de colonne d'entrée, ou le nom ou le chiffre ordinal d'une sortie colonne (expression SELECT), ou ce peut être une expression arbitraire formée de valeurs d'entrées colonnes. En cas d'ambiguïté, un nom GROUP BY sera interprété comme un nom d'entrée colonne d'avantage que comme un nom de sortie colonne.

Clause HAVING

a condition optionnelle HAVING a la forme générale :

HAVING boolean_expr
    
boolean_expr est la même que spécifié pour la clause WHERE.

HAVING spécifie une table groupée dérivée par l'élimination de groupes de lignes qui ne satisfont pas boolean_expr. HAVING est différent de WHERE: WHERE filtre les lignes individuelles avant l'application de GROUP BY, tandis que HAVING filtre les groupes de lignes crées par GROUP BY.

Chaque colonne référencée dans boolean_expr dera sans ambiguïté référence à un groupement de colonnes, à moins que la référence apparaisse dans une fonction agrégat.

Clause ORDER BY

ORDER BY expression [ ASC | DESC | USING operator ] [, ...]
    

Un ORDER BY peut être le nom ou le nombre ordinal d'une sortie colonne (expression SELECT), ou un expression arbitraire formée des valeurs d'entrées colonnes. En cas d'ambiguïté, un nom ORDER BY sera interprété comme un nom de sortie colonne.

Le nombre ordinal se réfère à la position ordinale (de gauche à droite) de la colonne résultante. Cette fonctionnalité fait qu'il est possible de définir un ordre sur la base d'une colonne qui n'a pas de nom propre. Ce n'est jamais absolument nécessaire car il est toujours possible d'assigner un nom à la colonne résultante en utilisant la clause AS, ex. :

SELECT title, date_prod + 1 AS newlen FROM films ORDER BY newlen;
    

Il est aussi possible de faire un ORDER BY sur des expressions arbitraires (une extension vers SQL92), incluant les champs qui n'apparaissent pas dans le résultat du SELECT. Ainsi l'instruction suivante est valide :

SELECT name FROM distributors ORDER BY code;
    
Une limitation de cette fonctionnalité est que la clause ORDER BY appliquée au résultat d'une requête UNION, INTERSECT, ou EXCEPT peut seulement spécifier un nom de sortie colonne ou un nombre, pas une expression.

Notez que si un ORDER BY est un simple nom qui apparie ensemble un résultat de nom de colonne et un nom d'entrée colonne, ORDER BY l'interprétera comme nom de colonne résultat. C'est à l'opposé du choix que GROUP BY ferait dans la même situation. Cette inconsistence est autorisée dans le standard SQL92.

Optionnellement on peut ajouter le mot-clé DESC (descendant) ou ASC (ascendant) après chaque nom de colonne dans la clause ORDER BY. Si non spécifié, ASC est prit par défaut. De façon alternative, un nom d'opérateur d'ordonnancement spécifique peut être spécifié. ASC est équivalent à USING < et DESC est équivalent à USING >.

La valeur null trie certaines autres valeurs dans le domaine. En d'autres termes, avec un tri ascendant les null font un tri à la fin et avec un tri descendant ils font le tri au début.

Clause UNION

table_query UNION [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start ]
    
table_query spécifie une expression de sélection sans une clause ORDER BY, FOR UPDATE, ou LIMIT. (ORDER BY et LIMIT peuvent être attachés à une sous-expression si elle est entre parenthèses. Sans les parenthèses, ces clauses seront appliquées au résultat de UNION, pas à son expression d'entrée côté droit).

L'opérateur UNION calcule l'ensemble des lignes retournées par les requêtes incluses. Les deux SELECT qui représentent les opérandes directes de UNION doivent produire le même nombre de colonnes, et les colonnes correspondantes doivent être de types compatibles.

Le résultat de UNION ne contient pas de lignes dupliquées à moins que l'option ALL soit spécifiée. ALL évite l'élimination des dupliquées.

Les opérateurs multiples UNION dans la même instruction SELECT sont évalués de gauche à droite, à moins qu'ils soient entre parenthèses.

Couramment, FOR UPDATE ne peut pas être spécifié soit pour un résultat UNION soit pour les entrées de UNION.

Clause INTERSECT

table_query INTERSECT [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start ]
    
table_query spécifie une expression de sélection sans la clause ORDER BY, FOR UPDATE, ou LIMIT.

INTERSECT est similaire à UNION, excepté qu'elle produit seulement les lignes apparaissant dans les deux sorties de requête, plus que les lignes apparaissant dans chacune séparément.

Le résultat d'un INTERSECT ne contient pas de lignes dupliquées sauf si l'option ALL option est spécifiée. Avec ALL, une ligne qui a m duplicats dans L et n duplicats dans R apparaitra min(m,n) fois.

Les opérateurs INTERSECT multiples dans la même instruction SELECT sont évalués de gauche à droite, sauf si des parenthèses l'indiquent autrement. INTERSECT lie plus étroitement que UNION --- ce qui fait que, A UNION B INTERSECT C sera lu comme A UNION (B INTERSECT C) sauf spécification différente par les parenthèses.

Clause EXCEPT

table_query EXCEPT [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start ]
    
table_query spécifie une expression de sélection sans une clause ORDER BY, FOR UPDATE, ou LIMIT.

EXCEPT est similaire à UNION, sauf qu'il ne produit que des lignes qui apparaissent dans la sortie gauche de la requête mais pas dans la sortie droite.

Le résultat de EXCEPT ne contient pas de lignes dupliquées sauf si l'option ALL option est spécifiée. Avec ALL, une ligne qui a m duplicats dans L et n duplicats dans R apparaitra comme max(m-n,0) fois.

Les opérateurs EXCEPT multiples dans la même instruction SELECT sont évalués de gauche à droite, sauf si des parenthèses l'indiquent autrement. EXCEPT lie au même niveau que UNION.

Clause LIMIT

    LIMIT { count | ALL }
    OFFSET start
    
count spécifie le nombre maximum de lignes à retourner, et start spécifie le nombre de lignes à sauter avant de lancer la récupération de lignes.

LIMIT vous permet de retrouver juste une partie des lignes qui sont générées par le reste de la requête. Si une limite est donnée, pas d'avantage de lignes ne seront retournées. Si un décalage est donné, ces diverses lignes seront sautées avant de lancer la récupération de lignes.

Quand on utilise LIMIT, c'est une bonne idée d'utiliser aussi la clause ORDER BY qui contraint les lignes résultantes en un ordre unique. Autrement vous obtiendrez un sous-ensemble imprévisible de lignes de la requête --- vous pouvez demander la dixième ligne dans une vingtaine de lignes, mais la dixième dans quel ordre ? Vous ne connaissez pas l'ordonnancement sauf si vous spécifiez ORDER BY.

Depuis PostgreSQL version 7.0, l'optimiseur de requête prend en compte LIMIT quand il génère son plan de requête, ainsi vous obtiendrez différents plans (rendant divers ordonnancements de lignes) selon que vous utilisez LIMIT ou OFFSET. Ainsi, l'utilisation de valeurs LIMIT/OFFSET différentes pour sélectionner différents sous-ensembles d'un résultat de requête donnera des résultats inconsistants sauf si vous forcez un résultat à être prévisible par l'ordonnancement de ORDER BY. ce n'est pas un bug; c'est une conséquence inhérente au fait que le SQL ne promet pas de délivrer les résultats d'une requête dans un ordre particulier sauf si ORDER BY est utiliser pour contraindre l'ordre.

Utilisation

Pour joindre la table films à la table distributors:

SELECT f.title, f.did, d.name, f.date_prod, f.kind
    FROM distributors d, films f
    WHERE f.did = d.did

           title           | did |   name           | date_prod  | kind
---------------------------+-----+------------------+------------+----------
 The Third Man             | 101 | British Lion     | 1949-12-23 | Drama
 The African Queen         | 101 | British Lion     | 1951-08-11 | Romantic
 Une Femme est une Femme   | 102 | Jean Luc Godard  | 1961-03-12 | Romantic
 Vertigo                   | 103 | Paramount        | 1958-11-14 | Action
 Becket                    | 103 | Paramount        | 1964-02-03 | Drama
 48 Hrs                    | 103 | Paramount        | 1982-10-22 | Action
 War and Peace             | 104 | Mosfilm          | 1967-02-12 | Drama
 West Side Story           | 105 | United Artists   | 1961-01-03 | Musical
 Bananas                   | 105 | United Artists   | 1971-07-13 | Comedy
 Yojimbo                   | 106 | Toho             | 1961-06-16 | Drama
 There's a Girl in my Soup | 107 | Columbia         | 1970-06-11 | Comedy
 Taxi Driver               | 107 | Columbia         | 1975-05-15 | Action
 Absence of Malice         | 107 | Columbia         | 1981-11-15 | Action
 Storia di una donna       | 108 | Westward         | 1970-08-15 | Romantic
 The King and I            | 109 | 20th Century Fox | 1956-08-11 | Musical
 Das Boot                  | 110 | Bavaria Atelier  | 1981-11-11 | Drama
 Bed Knobs and Broomsticks | 111 | Walt Disney      |            | Musical
(17 rows)

Pour faire le total de la colonne len de tous les films et grouper le résultat par kind :

SELECT kind, SUM(len) AS total FROM films GROUP BY kind;

   kind   | total
----------+-------
 Action   | 07:34
 Comedy   | 02:58
 Drama    | 14:28
 Musical  | 06:42
 Romantic | 04:38
(5 rows)

Pour faire le total de la colonne len de tous les films, groupant les résultats par kind et montrer quels groupes ont moins de 5 heures :

SELECT kind, SUM(len) AS total
    FROM films
    GROUP BY kind
    HAVING SUM(len) < INTERVAL '5 hour';

 kind     | total
----------+-------
 Comedy   | 02:58
 Romantic | 04:38
(2 rows)

Les deux exemples suivants sont des façons identiques de trier le résultat individuel selon le contenu de la seconde colonne (name) :

SELECT * FROM distributors ORDER BY name;
SELECT * FROM distributors ORDER BY 2;

 did |       name
-----+------------------
 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
(13 rows)

Cet exemple montre comment obtenir l'union des tables distributors et actors, en restreignant les résultats à ceux débutant par la lettre W dans chaque table. Seules les lignes distinctes sont recherchées, ainsi le mot-clé ALL est omis :

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

SELECT distributors.name
    FROM   distributors
    WHERE  distributors.name LIKE 'W%'
UNION
SELECT actors.name
    FROM   actors
    WHERE  actors.name LIKE 'W%';

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

Compatibilité

Extensions

PostgreSQL permet d'omettre la clause FROM d'une requête. Cette fonctionnalité vient du langage de requête PostQuel. Il est d'un usage franc pour calculer les résultats d'expressions de constante simple :

SELECT 2+2;

 ?column?
----------
        4
  
certains autres SGBDR introduisent une ligne fictive dans la table pour faire le from du select. Un usage moins évident est d'abréger un select normal sur une ou plusieurs tables :
SELECT distributors.* WHERE distributors.name = 'Westward';

 did | name
-----+----------
 108 | Westward
  
Ceci fonctionne car le FROM implicite est ajouté pour chaque table référencée dans la requête mais non mentionnée dans FROM. Comme c'est un raccourci pratique, il est facile d'en faire un usage érroné. Par exemple, la requête
SELECT distributors.* FROM distributors d;
  
est probablement une erreur; plus probablement l'utilisateur avait l'intention de
SELECT d.* FROM distributors d;
  
plutôt que la jointure non contrainte
SELECT distributors.* FROM distributors d, distributors distributors;
  
qui sera obtenue actuellement. Pour aider à détecter cette sorte d'erreur PostgreSQL à partir de 7.1 vous avertira si la forme FROM implicite est utilisée dans une requête qui contient aussi une clause FROM explicite.

SQL92

Clause SELECT

Dans le standard SQL92, le mot-clé optionnel AS n'est que du bruit et peut être omis sans affecter le comportement général. L'analyseur PostgreSQL nécessite ce mot-clé quand il renomme les colonnes de sortie car les fonctionnalités d'extensibilité de type conduisent à analyser les ambiguïtés dans ce contexte. AS est optionnel dans FROM, cependant.

La phrase DISTINCT ON ne fait pas partie du SQL92. Ni LIMIT et OFFSET.

En SQL92, une clause ORDER BY peut seulement utiliser les noms de colonnes ou les nombres résultant, tandis que la clause GROUP BY peut seulement utiliser les entrées noms de colonnes. PostgreSQL étend ces clauses de façon à permettre l'autre choix aussi bien (mais il utilise l'interprétation standard s'il y a ambiguïté). PostgreSQL permet aussi aux deux clauses de spécifier des expressions arbitraires. Notez que les noms apparaissant dans une expression seront toujours pris comme noms d'entrée colonne, pas comme noms de résultat colonne.

Clause UNION/INTERSECT/EXCEPT

La syntaxe SQL92 pour UNION/INTERSECT/EXCEPT permet une option supplémentaire CORRESPONDING BY :

 
table_query UNION [ALL]
    [CORRESPONDING [BY (column [,...])]]
    table_query
     

La clause CORRESPONDING BY n'est pas supportée par PostgreSQL.