To dziwactwo, jak wiele funkcji zwracających zestaw jest wykonywanych po wywołaniu w SELECT
-lista. Spodziewasz się, że wynik będzie iloczynem krzyżowym tych dwóch, ale tak to nie działa. W rzeczywistości jest to najniższa wspólna wielokrotność liczby wierszy z tych dwóch.
Zobacz:
- Dlaczego łączą się one inaczej w zależności od rozmiaru?
- Jak przepisać instrukcję SELECT ... CROSS JOIN LATERAL ... dla starszych wersji PostgreSQL?
Porównaj:
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)
Z tego powodu w PostgreSQL 9.2 i nowszych powinieneś używać LATERAL
zapytania, w których wywołujesz funkcje zwracające zestaw w FROM
klauzula:
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)
W starszych wersjach możesz użyć podzapytania-w-FROM, aby uniknąć wielu SRF w 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)