Documentation PostgreSQL 8.3.23 > Langage SQL > RequĂȘtes > Expressions de table | |
![]() |
Listes de sélection![]() |
Une expression de table calcule une table. L'expression de table contient une clause FROM qui peut ĂȘtre suivie des clauses WHERE, GROUP BY et HAVING. Les expressions triviales de table font simplement rĂ©fĂ©rence Ă une table sur le disque, une table de base, mais des expressions plus complexes peuvent ĂȘtre utilisĂ©es pour modifier ou combiner des tables de base de diffĂ©rentes façons.
Les clauses optionnelles WHERE, GROUP BY et HAVING dans l'expression de table spĂ©cifient un tube de transformations successives rĂ©alisĂ©es sur la table dĂ©rivĂ©e de la clause FROM. Toutes ces transformations produisent une table virtuelle fournissant les lignes Ă passer Ă la liste de sĂ©lection qui choisira les lignes Ă afficher de la requĂȘte.
La Clause FROM dérive une table à partir d'une ou plusieurs tables données dans une liste de référence dont les tables sont séparées par des virgules.
FROM reference_table [, reference_table [, ...]]
Une rĂ©fĂ©rence de table pourrait ĂȘtre un nom de table (avec en option le nom du schĂ©ma) ou une table dĂ©rivĂ©e comme une sous-requĂȘte, une table jointe ou une combinaison complexe de celles-ci. Si plus d'une rĂ©fĂ©rence de tables est listĂ©e dans la clause FROM, elle sont jointes pour former une table virtuelle intermĂ©diaire qui pourrait ĂȘtre le sujet des transformations des clauses WHERE, GROUP BY et HAVING, et est finalement le rĂ©sultat des expressions de table.
Lorsqu'une référence de table nomme une table qui est la table parent d'une table suivant la hiérarchie de l'héritage, la référence de table produit les lignes non seulement de la table mais aussi des descendants de cette table sauf si le mot clé ONLY précÚde le nom de la table. Néanmoins, la référence produit seulement les colonnes qui apparaissent dans la table nommée... toute colonne ajoutée dans une sous-table est ignorée.
Au lieu d'Ă©crire ONLY avant le nom de la table, vous pouvez Ă©crire * aprĂšs le nom de la table pour indiquer spĂ©cifiquement que les tables filles sont inclues. Ăcrire * n'est pas nĂ©cessaire car il s'agit du comportement par dĂ©faut (sauf si vous avez choisi de modifier la configuration de sql_inheritance). NĂ©anmoins, Ă©crire * peut ĂȘtre utile pour indiquer fortement que les tables filles seront parcourues.
Une table jointe est une table dérivée de deux autres tables (réelles ou dérivées) suivant les rÚgles du type de jointure particulier. Les jointures internes (inner), externes (outer) et croisées (cross) sont disponibles.
Types de jointures
T1 CROSS JOIN T2
Pour chaque combinaison de lignes provenant de T1 et T2, la table dérivée contiendra une ligne consistant de toutes les colonnes de T1 suivies de toutes les colonnes de T2. Si les tables ont respectivement N et M lignes, la table jointe en aura N * M.
FROM T1 CROSS JOIN T2 est équivalent à FROM T1, T2. C'est aussi équivalent à FROM T1 INNER JOIN T2 ON TRUE (voir ci-dessous).
T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON expression_booleenne T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 USING ( liste des colonnes jointes ) T1 NATURAL { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2
Les mots INNER et OUTER sont optionnels dans toutes les formes. INNER est la valeur par défaut ; LEFT, RIGHT et FULL impliquent une jointure externe.
La condition de la jointure est spécifiée dans la clause ON ou USING, ou implicitement par le mot NATURAL. La condition de jointure détermine les lignes des deux tables source considérées comme « correspondante », comme l'explique le paragraphe ci-dessous.
La clause ON est le type le plus gĂ©nĂ©ral de condition de jointure : il prend une expression boolĂ©enne du mĂȘme genre que celle utilisĂ©e dans une clause WHERE. Une paires de lignes de T1 et T2 correspondent si l'expression ON est Ă©valuĂ©e Ă vraie (true) pour ces deux lignes.
USING est la notation raccourcie : elle prend une liste de noms de colonnes, séparés par des virgules, que les tables jointes ont en commun, et forme une condition de jointure spécifiant l'égalité de chacune de ces paires de colonnes. De plus, la sortie de JOIN USING a une colonne pour chaque paires égales des colonnes en entrée, suivies par toutes les autres colonnes de chaque table. Du coup, USING (a, b, c) est équivalent à ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) avec l'exception que si ON est utilisé, il y aura deux colonnes a, b, puis c dans le résultat, alors qu'avec USING, il n'y en aurait eu qu'une de chaque.
Enfin, NATURAL est un format raccourci de USING : il forme une liste USING consistant exactement des noms de colonnes apparaissant à la fois dans les deux tables en entrée. Comme avec USING, ces colonnes apparaissent seulement une fois dans la table de sortie.
Les types possibles de jointures qualifiées sont :
Pour chaque ligne R1 de T1, la table jointe a une ligne pour chaque ligne de T2 satisfaisant la condition de jointure avec R1.
Tout d'abord, une jointure interne est réalisée. Puis, pour chaque ligne de T1 qui ne satisfait pas la condition de jointure avec les lignes de T2, une ligne jointe est ajoutée avec des valeurs NULL dans les colonnes de T2. Du coup, la table jointe a au moins une ligne pour chaque ligne de T1 quelque soient les conditions.
Tout d'abord, une jointure interne est réalisée. Puis, pour chaque ligne de T2 qui ne satisfait pas la condition de jointure avec les lignes de T1, une ligne jointe est ajoutée avec des valeurs NULL dans les colonnes de T1. C'est l'inverse d'une jointure gauche : la table résultante aura une ligne pour chaque ligne de T2 quelque soient les conditions.
Tout d'abord, une jointure interne est réalisée. Puis, pour chaque ligne de T1 qui ne satisfait pas la condition de jointure avec les lignes de T2, une ligne jointe est ajoutée avec des valeurs NULL dans les colonnes de T2. De plus, pour chaque ligne de T2 qui ne satisfait pas la condition de jointure avec les lignes de T1, une ligne jointe est ajoutée avec des valeurs NULL dans les colonnes de T1.
Les jointures de tous les types peuvent ĂȘtre chaĂźnĂ©es ensemble ou imbriquĂ©es : soit les deux soit une des deux, parmi T1 et T2, peuvent ĂȘtre des tables. Les parenthĂšses peuvent ĂȘtre utilisĂ©es autour des clauses JOIN pour contrĂŽler l'ordre de jointure. En l'absence de parenthĂšses, les clauses JOIN sont imbriquĂ©es de gauche Ă droite.
Pour rassembler tout ceci, supposons que nous avons une table t1 :
no | nom ----+------ 1 | a 2 | b 3 | c
et une table t2 :
no | valeur ----+------- 1 | xxx 3 | yyy 5 | zzz
nous obtenons les résultats suivants pour les différentes jointures :
=> SELECT * FROM t1 CROSS JOIN t2; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 1 | a | 3 | yyy 1 | a | 5 | zzz 2 | b | 1 | xxx 2 | b | 3 | yyy 2 | b | 5 | zzz 3 | c | 1 | xxx 3 | c | 3 | yyy 3 | c | 5 | zzz (9 rows) => SELECT * FROM t1 INNER JOIN t2 ON t1.no = t2.no; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 3 | c | 3 | yyy (2 rows) => SELECT * FROM t1 INNER JOIN t2 USING (no); no | nom | valeur ----+-----+------- 1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 NATURAL INNER JOIN t2; no | nom | valeur ----+-----+------- 1 | a | xxx 3 | c | yyy (2 rows) => SELECT * FROM t1 LEFT JOIN t2 ON t1.no = t2.no; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | 3 | yyy (3 rows) => SELECT * FROM t1 LEFT JOIN t2 USING (no); no | nom | valeur ----+-----+------- 1 | a | xxx 2 | b | 3 | c | yyy (3 rows) => SELECT * FROM t1 RIGHT JOIN t2 ON t1.no = t2.no; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 3 | c | 3 | yyy | | 5 | zzz (3 rows) => SELECT * FROM t1 FULL JOIN t2 ON t1.no = t2.no; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | 3 | yyy | | 5 | zzz (4 rows)
La condition de jointure spĂ©cifiĂ©e avec ON peut aussi contenir des conditions sans relation directe avec la jointure. Ceci est utile pour quelques requĂȘtes mais son utilisation doit avoir Ă©tĂ© rĂ©flĂ©chie. Par exemple :
=> SELECT * FROM t1 LEFT JOIN t2 ON t1.no = t2.no AND t2.valeur = 'xxx'; no | nom | no | valeur ----+-----+----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | | (3 rows)
Un nom temporaire peut ĂȘtre donnĂ© aux tables et aux rĂ©fĂ©rences de tables complexe, qui sera ensuite utilisĂ© pour rĂ©fĂ©rencer la table dĂ©rivĂ©e dans la suite de la requĂȘte. Cela s'appelle un alias de table.
Pour créer un alias de table, écrivez
FROM reference_table AS alias
ou
FROM reference_table alias
Le mot clĂ© AS n'est pas obligatoire. alias peut ĂȘtre tout identifiant.
Une application typique des alias de table est l'affectation d'identifieurs courts pour les noms de tables longs, ce qui permet de garder des clauses de jointures lisibles. Par exemple :
SELECT * FROM nom_de_table_tres_tres_long s JOIN un_autre_nom_tres_long a ON s.id = a.no;
L'alias devient le nouveau nom de rĂ©fĂ©rence de la table pour la requĂȘte courante -- il n'est plus possible de rĂ©fĂ©rencer la table avec son nom d'origine. Du coup :
SELECT * FROM ma_table AS m WHERE ma_table.a > 5;
n'est pas valide suivant le standard SQL. Dans PostgreSQLâą, ceci amĂšnera une erreur si la variable add_missing_from est dĂ©sactivĂ©e (off, valeur par dĂ©faut). S'il est activĂ© (on), une rĂ©fĂ©rence vers une table implicite sera ajoutĂ©e Ă la clause FROM, de façon Ă ce que la requĂȘte soit exĂ©cutĂ©e comme si elle Ă©tait Ă©crite ainsi :
SELECT * FROM ma_table AS m, ma_table AS ma_table WHERE ma_table.a > 5;
Cela résultera en une jointure croisée, ce qui n'est habituellement pas ce que vous voulez.
Les alias de table sont disponibles principalement pour aider Ă l'Ă©criture de requĂȘte mais ils deviennent nĂ©cessaires pour joindre une table avec elle-mĂȘme, par exemple :
SELECT * FROM personnes AS mere JOIN personnes AS enfant ON mere.id = enfant.mere_id;
De plus, un alias est requis si la rĂ©fĂ©rence de la table est une sous-requĂȘte (voir la Section 7.2.1.3, « Sous-requĂȘtes »).
Les parenthÚses sont utilisées pour résoudre les ambiguïtés. Dans l'exemple suivant, la premiÚre instruction affecte l'alias b à la deuxiÚme instance de ma_table mais la deuxiÚme instruction affecte l'alias au résultat de la jonction :
SELECT * FROM ma_table AS a CROSS JOIN ma_table AS b ... SELECT * FROM (ma_table AS a CROSS JOIN ma_table) AS b ...
Une autre forme d'alias de tables donne des noms temporaires aux colonnes de la table ainsi qu'Ă la table :
FROM reference_table [AS] alias ( colonne1 [, colonne2 [, ...]] )
Si le nombre d'alias de colonnes spĂ©cifiĂ© est plus petit que le nombre de colonnes dont dispose la table rĂ©elle, les colonnes suivantes ne sont pas renommĂ©es. Cette syntaxe est particuliĂšrement utile dans le cas de jointure avec la mĂȘme table ou dans le cas de sous-requĂȘtes.
Quand un alias est appliqué à la sortie d'une clause JOIN en utilisant n'importe laquelle de ces formes, l'alias cache le nom original à l'intérieur du JOIN. Par exemple :
SELECT a.* FROM ma_table AS a JOIN ta_table AS b ON ...
est du SQL valide mais :
SELECT a.* FROM (ma_table AS a JOIN ta_table AS b ON ...) AS c
n'est pas valide : l'alias de table a n'est pas visible en dehors de l'alias c.
Une sous-requĂȘte spĂ©cifiant une table dĂ©rivĂ©e doit ĂȘtre enfermĂ©e dans des parenthĂšses et doit se voir affectĂ© un alias de table (voir la Section 7.2.1.2, « Alias de table et de colonne »). Par exemple :
FROM (SELECT * FROM table1) AS nom_alias
Cet exemple est Ă©quivalent Ă FROM table1 AS nom_alias. Des cas plus intĂ©ressants, qui ne peuvent pas ĂȘtre rĂ©duit Ă une jointure pleine, surviennent quand la sous-requĂȘte implique un groupement ou un agrĂ©gat.
Uns sous-requĂȘte peut aussi ĂȘtre une liste VALUES :
FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) AS noms(prenom, nom)
De nouveau, un alias de table est requis. Affecter des noms d'alias aux colonnes de la liste VALUES est en option mais c'est une bonne pratique. Pour plus d'informations, voir Section 7.7, « Listes VALUES ».
Les fonctions de table sont des fonctions produisant un ensemble de lignes composĂ©es de types de donnĂ©es de base (types scalaires) ou de types de donnĂ©es composites (lignes de table). Elles sont utilisĂ©es comme une table, une vue ou une sous-requĂȘte de la clause FROM d'une requĂȘte. Les colonnes renvoyĂ©es par les fonctions de table peuvent ĂȘtre incluses dans une clause SELECT, JOIN ou WHERE de la mĂȘme maniĂšre qu'une colonne de table, vue ou sous-requĂȘte.
Si une fonction de table renvoie un type de donnĂ©es de base, la colonne de rĂ©sultat est nommĂ©e comme la fonction. Si la fonction renvoie un type composite, les colonnes rĂ©sultantes ont le mĂȘme nom que les attributs individuels du type.
Une fonction de table peut avoir un alias dans la clause FROM mais elle peut ĂȘtre laissĂ©e sans alias. Si une fonction est utilisĂ©e dans la clause FROM sans alias, le nom de la fonction est utilisĂ© comme nom de table rĂ©sultante.
Quelques exemples :
CREATE TABLE truc (trucid int, trucsousid int, trucnom text); CREATE FUNCTION recuptruc(int) RETURNS SETOF foo AS $$ SELECT * FROM truc WHERE trucid = $1; $$ LANGUAGE SQL; SELECT * FROM recuptruc(1) AS t1; SELECT * FROM truc WHERE trucsousid IN (select trucsousid from recuptruc(truc.trucid) z where z.trucid = truc.trucid); CREATE VIEW vue_recuptruc AS SELECT * FROM recuptruc(1); SELECT * FROM vue_recuptruc;
Dans certains cas, il est utile de dĂ©finir des fonctions de table pouvant renvoyer des ensembles de colonnes diffĂ©rentes suivant la façon dont elles sont appelĂ©es. Pour supporter ceci, la fonction de table est dĂ©clarĂ©e comme renvoyant le pseudotype record. Quand une telle fonction est utilisĂ©e dans une requĂȘte, la structure de ligne attendue doit ĂȘtre spĂ©cifiĂ©e dans la requĂȘte elle-mĂȘme, de façon Ă ce que le systĂšme sache comment analyser et planifier la requĂȘte. ConsidĂ©rez cet exemple :
SELECT * FROM dblink('dbname=mabd', 'select proname, prosrc from pg_proc') AS t1(proname nom, prosrc text) WHERE proname LIKE 'bytea%';
La fonction dblink exĂ©cute une requĂȘte distante (voir contrib/dblink). Elle dĂ©clare renvoyer le type record car elle pourrait ĂȘtre utilisĂ©e pour tout type de requĂȘte. L'ensemble de colonnes rĂ©elles doit ĂȘtre spĂ©cifiĂ© dans la requĂȘte appelante de façon Ă ce que l'analyseur sache, par exemple, comment Ă©tendre *.
La syntaxe de la Clause WHERE est
WHERE condition_recherche
oĂč condition_recherche est toute expression de valeur (voir la Section 4.2, « Expressions de valeurs ») renvoyant une valeur de type boolean.
AprÚs le traitement de la clause FROM, chaque ligne de la table virtuelle dérivée est vérifiée avec la condition de recherche. Si le résultat de la vérification est positif (true), la ligne est conservée dans la table de sortie, sinon (c'est-à -dire si le résultat est faux ou nul), la ligne est abandonnée. La condition de recherche référence typiquement au moins quelques colonnes de la table générée dans la clause FROM ; ceci n'est pas requis mais, dans le cas contraire, la clause WHERE n'aurait aucune utilité.
La condition de jointure d'une jointure interne peut ĂȘtre Ă©crite soit dans la clause WHERE soit dans la clause JOIN. Par exemple, ces expressions de tables sont Ă©quivalentes :
FROM a, b WHERE a.id = b.id AND b.val > 5
et :
FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
ou mĂȘme peut-ĂȘtre :
FROM a NATURAL JOIN b WHERE b.val > 5
Laquelle vous utilisez est plutĂŽt une affaire de style. La syntaxe JOIN dans la clause FROM n'est probablement pas aussi portable vers les autres systĂšmes de gestion de bases de donnĂ©es SQL. Pour les jointures externes, il n'y a pas d'autres choix : elles doivent ĂȘtre faites dans la clause FROM. Une clause ON/USING d'une jointure externe n'est pas Ă©quivalente Ă une condition WHERE parce qu'elle dĂ©termine l'ajout de lignes (pour les lignes qui ne correspondent pas en entrĂ©e) ainsi que pour la suppression de lignes dans le rĂ©sultat final.
Voici quelques exemples de clauses WHERE :
SELECT ... FROM fdt WHERE c1 > 5 SELECT ... FROM fdt WHERE c1 IN (1, 2, 3) SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2) SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) AND 100 SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
fdt est la table dĂ©rivĂ©e dans la clause FROM. Les lignes qui ne correspondent pas Ă la condition de recherche de la clause WHERE sont Ă©liminĂ©es de la table fdt. Notez l'utilisation de sous-requĂȘtes scalaires en tant qu'expressions de valeurs. Comme n'importe quelle autre requĂȘte, les sous-requĂȘtes peuvent employer des expressions de tables complexes. Notez aussi comment fdt est rĂ©fĂ©rencĂ©e dans les sous-requĂȘtes. Qualifier c1 comme fdt.c1 est seulement nĂ©cessaire si c1 est aussi le nom d'une colonne dans la table d'entrĂ©e dĂ©rivĂ©e de la sous-requĂȘte. Mais qualifier le nom de colonne ajoute Ă la clartĂ© mĂȘme lorsque cela n'est pas nĂ©cessaire. Cet exemple montre comment le nom de colonne d'une requĂȘte externe est Ă©tendue dans les requĂȘtes internes.
AprĂšs avoir passĂ© le filtre WHERE, la table d'entrĂ©e dĂ©rivĂ©e peut ĂȘtre sujette Ă un regroupement en utilisant la clause GROUP BY et Ă une Ă©limination de groupe de lignes avec la clause HAVING.
SELECT liste_selection FROM ... [WHERE ...] GROUP BY reference_colonne_regroupement[,reference_colonne_regroupement]...
La Clause GROUP BY est utilisĂ©e pour regrouper les lignes d'une table partageant les mĂȘmes valeurs dans toutes les colonnes prĂ©cisĂ©es. L'ordre dans lequel ces colonnes sont indiquĂ©es importe peu. L'effet est de combiner chaque ensemble de lignes partageant des valeurs communes en un seul groupe de ligne reprĂ©sentant toutes les lignes du groupe. Ceci est fait pour Ă©liminer les redondances dans la sortie et/ou pour calculer les agrĂ©gats s'appliquant Ă ces groupes. Par exemple :
=> SELECT * FROM test1; x | y ---+--- a | 3 c | 2 b | 5 a | 1 (4 rows) => SELECT x FROM test1 GROUP BY x; x --- a b c (3 rows)
Dans la seconde requĂȘte, nous n'aurions pas pu Ă©crire SELECT * FROM test1 GROUP BY x parce qu'il n'existe pas une seule valeur pour la colonne y pouvant ĂȘtre associĂ© avec chaque autre groupe. Les colonnes de regroupement peuvent ĂȘtre rĂ©fĂ©rencĂ©es dans la liste de sĂ©lection car elles ont une valeur constante unique par groupe.
En gĂ©nĂ©ral, si une table est groupĂ©e, les colonnes qui ne sont pas utilisĂ©es dans le regroupement ne peuvent pas ĂȘtre rĂ©fĂ©rencĂ©es sauf dans les expressions d'agrĂ©gats. Voici un exemple d'expressions d'agrĂ©gat :
=> SELECT x, sum(y) FROM test1 GROUP BY x; x | sum ---+----- a | 4 b | 5 c | 2 (3 rows)
Ici, sum est la fonction d'agrégat qui calcule une seule valeur pour le groupe entier. La Section 9.18, « Fonctions d'agrégat » propose plus d'informations sur les fonctions d'agrégats disponibles.
Le regroupement sans expressions d'agrégats calcule effectivement l'ensemble les valeurs distinctes d'une colonne. Ceci peut aussi se faire en utilisant la clause DISTINCT (voir la Section 7.3.3, « DISTINCT »).
Voici un autre exemple : il calcule les ventes totales pour chaque produit (plutĂŽt que le total des ventes sur tous les produits) :
SELECT produit_id, p.nom, (sum(v.unite) * p.prix) AS ventes FROM produits p LEFT JOIN ventes v USING (produit_id) GROUP BY produit_id, p.nom, p.prix;
Dans cet exemple, les colonnes produit_id, p.nom et p.prix doivent ĂȘtre dans la clause GROUP BY car elles sont rĂ©fĂ©rencĂ©es dans la liste de sĂ©lection de la requĂȘte (suivant la façon dont est conçue la table produits, le nom et le prix pourraient ĂȘtre totalement dĂ©pendants de l'ID du produit, donc des regroupements supplĂ©mentaires pourraient thĂ©oriquement ĂȘtre inutiles mais ceci n'est pas encore implĂ©mentĂ©). La colonne s.unite n'a pas besoin d'ĂȘtre dans la liste GROUP BY car elle est seulement utilisĂ©e dans l'expression de l'agrĂ©gat (sum(...)) reprĂ©sentant les ventes d'un produit. Pour chaque produit, la requĂȘte renvoie une ligne de rĂ©sumĂ© sur les ventes de ce produit.
En SQL strict, GROUP BY peut seulement grouper les colonnes de la table source mais PostgreSQL⹠étend ceci en autorisant GROUP BY à grouper aussi les colonnes de la liste de sélection. Grouper par expressions de valeurs au lieu de simples noms de colonnes est aussi permis.
Si une table a Ă©tĂ© groupĂ©e en utilisant la clause GROUP BY mais que seuls certains groupes sont intĂ©ressants, la clause HAVING peut ĂȘtre utilisĂ©e, comme une clause WHERE, pour Ă©liminer les groupes d'une table groupĂ©e. Voici la syntaxe :
SELECT liste_selection FROM ... [WHERE ...] GROUP BY ... HAVING expression_booléenne
Les expressions de la clause HAVING peuvent référer à la fois aux expressions groupées et aux expressions non groupées (ce qui impliquent nécessairement une fonction d'agrégat).
Exemple :
=> SELECT x, sum(y) FROM test1 GROUP BY x HAVING sum(y) > 3; x | sum ---+----- a | 4 b | 5 (2 rows) => SELECT x, sum(y) FROM test1 GROUP BY x HAVING x < 'c'; x | sum ---+----- a | 4 b | 5 (2 rows)
De nouveau, un exemple plus réaliste :
SELECT produit_id, p.nom, (sum(v.unite) * (p.prix - p.cout)) AS profit FROM produits p LEFT JOIN ventes v USING (produit_id) WHERE v.date > CURRENT_DATE - INTERVAL '4 weeks' GROUP BY produit_id, p.nom, p.prix, p.cout HAVING sum(p.prix * s.unite) > 5000;
Dans l'exemple ci-dessus, la clause WHERE sĂ©lectionne les lignes par une colonne qui n'est pas groupĂ©e (l'expression est vraie seulement pour les ventes des quatre derniĂšres semaines) alors que la clause HAVING restreint la sortie aux groupes dont le total des ventes dĂ©passe 5000. Notez que les expressions d'agrĂ©gats n'ont pas besoin d'ĂȘtre identiques dans toutes les parties d'une requĂȘte.