C'est une bizarrerie de la façon dont plusieurs fonctions de retour d'ensemble sont exécutées lorsqu'elles sont invoquées dans le SELECT
-liste. Vous vous attendez à ce que le résultat soit le produit croisé des deux, mais ce n'est pas ainsi que cela fonctionne. C'est en fait le multiple commun le plus bas du nombre de lignes des deux.
Voir :
- Pourquoi ces liens diffèrent-ils en fonction de la taille ?
- Comment réécrire une instruction SELECT ... CROSS JOIN LATERAL ... pour les anciennes versions de PostgreSQL ?
Comparez :
test=> SELECT generate_series(1,3) aval, generate_series(1,4) bval;
aval | bval
------+------
1 | 1
2 | 2
3 | 3
1 | 4
2 | 1
3 | 2
1 | 3
2 | 4
3 | 1
1 | 2
2 | 3
3 | 4
(12 rows)
test=> SELECT generate_series(1,3) aval, generate_series(1,3) bval;
aval | bval
------+------
1 | 1
2 | 2
3 | 3
(3 rows)
Pour cette raison, sur PostgreSQL 9.2 et supérieur, vous devez utiliser LATERAL
requêtes où vous invoquez des fonctions de retour d'ensemble dans le FROM
clause :
test=> SELECT aval, bval FROM generate_series(1,3) aval CROSS JOIN LATERAL generate_series(1,3) bval;
aval | bval
------+------
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
(9 rows)
test=> SELECT aval, bval FROM generate_series(1,3) aval CROSS JOIN LATERAL generate_series(1,4) bval;
aval | bval
------+------
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 2
2 | 3
2 | 4
3 | 1
3 | 2
3 | 3
3 | 4
(12 rows)
Sur les anciennes versions, vous pouvez utiliser une sous-requête-dans-FROM pour éviter d'avoir plusieurs SRF dans un terme SELECT :
test=> SELECT generate_series(1,3) aval, bval FROM (SELECT generate_series(1,4)) AS x(bval);
aval | bval
------+------
1 | 1
2 | 1
3 | 1
1 | 2
2 | 2
3 | 2
1 | 3
2 | 3
3 | 3
1 | 4
2 | 4
3 | 4
(12 rows)