Postgresql

在 PostgreSQL 中加入多個沒有重複結果且沒有 UNION 的表

  • March 21, 2022

假設我們在 PostgreSQL 中有兩個表 A 和 B:

一種

我想得到以下結果:

如果我查詢如下內容 - 我將得到 6 行而不是 5 行,因為 B0 中的所有行都將與 B1 中的所有行混合,如果 B0 或 B1 有更多行,結果行數將逐漸增加:

SELECT A.title, B0.element_name, B1.element_name
LEFT JOIN B B0 ON A.first_group_id = B0.group_id
LEFT JOIN B B1 ON A.second_group_id = B1.group_id
FROM A;

我可以通過使用 UNION 來實現所需的行為,但我想知道是否有更有效的方法來做到這一點?特別是當需要以相同的方式進行兩個以上的 JOIN 時。

可能有更快的方法。適用於您的最小展示:

SELECT a.title
    , CASE WHEN b.group_id = a.first_group_id  THEN b.element_name END AS first_group
    , CASE WHEN b.group_id = a.second_group_id THEN b.element_name END AS second_group
FROM   a, b;

基本上,加入一次以避免重複。

但是你的問題留下了很大的解釋空間。

很有可能,你有額外的限制。這可能是您真正需要的:

SELECT a.title
    , CASE WHEN b.group_id = a.first_group_id  THEN b.element_name END AS first_group
    , CASE WHEN b.group_id = a.second_group_id THEN b.element_name END AS second_group
FROM   a
LEFT   JOIN b ON b.group_id IN (a.first_group_id, a.second_group_id)
ORDER  BY a.title, b.group_id, element_name;

db<>在這裡擺弄

另外,您可能需要一個額外的列來定義 table 中的 order B

並且UNION ALL可能仍然更快,具體取決於未公開的細節。


LEFT JOIN在範例中獲得 2x 的 6 行的原因:

這只是任務的錯誤方法。

避免兩次查詢表的一個巧妙選擇是首先取消透視A

您需要一些CASE表達式,因為您還想拆分element_name回不同的列。

不太擅長 Postgres,我的語法可能略有偏差

SELECT
   A.title,
   CASE WHEN A.first_group_id  = v.group_id THEN B.element_name END AS element_name0,
   CASE WHEN A.second_group_id = v.group_id THEN B.element_name END AS element_name1
FROM A
INNER JOIN LATERAL (VALUES
   (A.first_group_id),
   (A.second_group_id)
) AS v(group_id)
LEFT JOIN B ON v.group_id = B.group_id;

引用自:https://dba.stackexchange.com/questions/289875