PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Quel est le comportement attendu pour plusieurs fonctions renvoyant des ensembles dans la clause SELECT ?

Postgres 10 ou version ultérieure

ajoute des valeurs nulles pour les ensembles plus petits. Démo avec generate_series() :

SELECT generate_series( 1,  2) AS row2
     , generate_series(11, 13) AS row3
     , generate_series(21, 24) AS row4;
row2 | row3 | row4
-----+------+-----
   1 |   11 |   21
   2 |   12 |   22
null |   13 |   23
null | null |   24

dbfiddle ici

Le manuel de Postgres 10 :

S'il y a plus d'une fonction renvoyant un ensemble dans la liste de sélection de la requête, le comportement est similaire à ce que vous obtenez en plaçant les fonctions dans un seul LATERAL ROWS FROM( ... ) FROM -article de clause. Pour chaque ligne de la requête sous-jacente, il existe une ligne de sortie utilisant le premier résultat de chaque fonction, puis une ligne de sortie utilisant le second résultat, et ainsi de suite. Si certaines des fonctions renvoyant un ensemble produisent moins de sorties que d'autres, des valeurs nulles sont remplacées par les données manquantes, de sorte que le nombre total de lignes émises pour une ligne sous-jacente soit le même que pour la fonction renvoyant un ensemble qui a produit le plus de sorties. Ainsi, les fonctions renvoyant des ensembles s'exécutent "en parallèle" jusqu'à ce qu'elles soient toutes épuisées, puis l'exécution se poursuit avec la ligne sous-jacente suivante.

Cela met fin au comportement traditionnellement étrange.

Postgres 9.6 ou version antérieure

Le nombre de lignes de résultats (quelque peu surprenant !) est le multiple commun le plus bas de tous les ensembles dans le même SELECT liste. (Agit uniquement comme un CROSS JOIN s'il n'y a pas de diviseur commun à toutes les tailles d'ensemble !) Démo :

SELECT generate_series( 1,  2) AS row2
     , generate_series(11, 13) AS row3
     , generate_series(21, 24) AS row4;
row2 | row3 | row4
-----+------+-----
   1 |   11 |   21
   2 |   12 |   22
   1 |   13 |   23
   2 |   11 |   24
   1 |   12 |   21
   2 |   13 |   22
   1 |   11 |   23
   2 |   12 |   24
   1 |   13 |   21
   2 |   11 |   22
   1 |   12 |   23
   2 |   13 |   24

dbfiddle ici

Documenté dans le manuel pour Postgres 9.6 le chapitre Fonctions SQL renvoyant des ensembles , ainsi que la recommandation pour l'éviter :

Remarque :Le problème clé avec l'utilisation des fonctions de retour d'ensemble dans la liste de sélection, plutôt que le FROM clause, est que mettre plus d'une fonction renvoyant un ensemble dans la même liste de sélection ne se comporte pas très sensiblement. (Ce que vous obtenez réellement si vous le faites est un nombre de lignes de sortie égal au plus petit commun multiple du nombre de lignes produites par chaque fonction renvoyant un ensemble. ) Le LATERAL La syntaxe produit des résultats moins surprenants lors de l'appel de plusieurs fonctions renvoyant des ensembles et doit généralement être utilisée à la place.

J'insiste sur moi.

Une seule fonction de retour d'ensemble est OK (mais toujours plus propre dans le FROM list), mais multiples dans le même SELECT la liste est découragée maintenant. C'était une fonctionnalité utile avant que nous ayons LATERAL rejoint. Maintenant, ce n'est plus qu'un lest historique.

Connexe :

  • Unnest() parallèle et ordre de tri dans PostgreSQL
  • Désimbriquer plusieurs baies en parallèle
  • Quelle est la différence entre LATERAL JOIN et une sous-requête dans PostgreSQL ?