aRe*_*ess 4 sql postgresql cartesian-product
作为定义:两组的笛卡尔乘积是这些集合的所有可能对的集合,因此{A,B} x {a,b} = {(A,a),(A,b),(B,a ),(b,b)}.
现在我想将这样的笛卡尔积插入数据库表(每对作为一行).它旨在用每个对的默认值填充表,因此此时数据(即两组)不存在于数据库中.
任何想法如何用postgresql实现这一点?
编辑:
在Grzegorz Szpetkowski的回答的帮助下,我能够生成一个能够实现我想要实现的目标的查询,但它确实不是最漂亮的查询.假设我要插入集合{1,2,3}和{'A','B','C'}的笛卡尔积.
INSERT INTO "Test"
SELECT * FROM
(SELECT 1 UNION SELECT 2 UNION SELECT 3) P
CROSS JOIN
(SELECT 'A' UNION SELECT 'B' UNION SELECT 'C') Q
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来做到这一点?
编辑2: 接受的答案很好,但我发现另一个版本,如果它变得更复杂可能是适当的:
CREATE TEMP TABLE "Numbers" (ID integer) ON COMMIT DROP;
CREATE TEMP TABLE "Chars" (Char character varying) ON COMMIT DROP;
INSERT INTO "Numbers" (ID) VALUES (1),(2),(3);
INSERT INTO "Chars" (Char) VALUES ('A'),('B'),('C');
INSERT INTO "Test"
SELECT * FROM
"Numbers"
CROSS JOIN
"Chars";
Run Code Online (Sandbox Code Playgroud)
我不确定这是否真的回答了你的问题,但在PostgreSQL中CROSS JOIN定义为:
对于T1和T2的每个可能的行组合(即 笛卡尔积),连接表将包含一行,其中包含T1中的所有列,后跟T2中的所有列.如果表分别具有N和M行,则连接表将具有N*M行.
从T1 CROSS JOIN T2相当于FROM T1,T2.它也相当于FROM T1 INNER JOIN T2 ON TRUE(见下文).
编辑:
一种方法是使用VALUES Lists(注意,事实上你没有订单,使用ORDER BY子句来获得一些排序):
SELECT N AS number, L AS letter FROM
(VALUES (1), (2), (3)) a(N)
CROSS JOIN
(VALUES ('A'), ('B'), ('C')) b(L);
Run Code Online (Sandbox Code Playgroud)
结果:
number | letter
--------+--------
1 | A
1 | B
1 | C
2 | A
2 | B
2 | C
3 | A
3 | B
3 | C
(9 rows)
Run Code Online (Sandbox Code Playgroud)
BTW:
对于更多数字,我相信它是使用generate_series函数的句柄,例如:
SELECT n AS number, chr(ascii('A') + L - 1) AS letter
FROM
generate_series(1, 5) N
CROSS JOIN
generate_series(1, 5) L
ORDER BY N, L;
Run Code Online (Sandbox Code Playgroud)
结果:
number | letter
--------+--------
1 | A
1 | B
1 | C
1 | D
1 | E
2 | A
2 | B
2 | C
2 | D
2 | E
3 | A
3 | B
3 | C
3 | D
3 | E
4 | A
4 | B
4 | C
4 | D
4 | E
5 | A
5 | B
5 | C
5 | D
5 | E
(25 rows)
Run Code Online (Sandbox Code Playgroud)