5

如定义:两个集合的笛卡尔积是这些集合的所有可能对的集合,所以 {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";
4

1 回答 1

11

我不确定这是否真的回答了你的问题,但在 PostgreSQL 中CROSS JOIN定义为:

对于 T1 和 T2 中的每个可能的行组合(即 笛卡尔积),连接表将包含一行,该行由 T1 中的所有列和 T2 中的所有列组成。如果表分别有 N 和 M 行,则连接表将有 N * M 行。

FROM T1 CROSS JOIN T2 等价于 FROM T1, T2。它也等同于 FROM T1 INNER JOIN T2 ON TRUE(见下文)。

编辑:

一种方法是使用VALUES 列表(请注意,实际上您没有顺序,使用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)
于 2011-07-13T18:08:29.757 回答