Es una peculiaridad de cómo se ejecutan múltiples funciones de devolución de conjuntos cuando se invocan en SELECT
-lista. Esperas que el resultado sea el producto cruzado de los dos, pero no es así como funciona. En realidad, es el múltiplo común más bajo de los recuentos de filas de los dos.
Ver:
- ¿Por qué estos se unen de manera diferente según el tamaño?
- ¿Cómo reescribir una instrucción SELECT... CROSS JOIN LATERAL... para versiones anteriores de PostgreSQL?
Comparar:
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)
Por esta razón, en PostgreSQL 9.2 y superior, debe usar LATERAL
consultas en las que invoca funciones de devolución de conjuntos en FROM
cláusula:
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)
En versiones anteriores, puede usar una subconsulta DESDE para evitar tener múltiples SRF en un término 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)