作为定义:两个集合的笛卡尔乘积是这些集合的所有可能对的集合,因此{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
有没有更好的方法呢?
EDIT2: 接受的答案很好,但我找到了另一个版本,如果它变得更复杂可能是合适的:
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";
答案 0 :(得分:8)
我不确定这是否真的能解答您的问题,但在PostgreSQL中,CROSS JOIN
定义为:
对于T1和T2的每一个可能的行组合(即a 笛卡儿积),连接表将包含一行 T1中的所有列后跟T2中的所有列。如果表有N. 分别为M行和M行,连接表将有N * M行。
FROM T1 CROSS JOIN T2相当于FROM T1,T2。也是 相当于FROM T1 INNER JOIN T2为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);
结果:
number | letter
--------+--------
1 | A
1 | B
1 | C
2 | A
2 | B
2 | C
3 | A
3 | B
3 | C
(9 rows)
<强>顺便说一句强>:
对于更多数字,我认为可以使用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;
结果:
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)