Postgresql

從“組合,或者內部連接”中獲取結果

  • August 30, 2020

我有一種感覺,這一定被問過很多次了,但我就是找不到解決方案,甚至找不到可能是因為難以解釋的問題。

我們都知道內連接基本上給出了兩個表的“交集”。因此,多個內連接給出了所有表的交集。但是,我希望獲得一個內部連接,該連接獲得表 B 與 A表 C 與 A的交集。

就像獲得所有組織的請求一樣,我要麼是版主,要麼是管理員。

SELECT *
FROM organization
INNER JOIN moderator_organization
 ON organization.id = moderator_organization.organization AND moderator_organization.user = 10
INNER JOIN admin_organization
 ON organization.id = admin_organization.organization AND admin_organization.user = 10

然而,上面只會選擇使用者(ID 為 10)既是管理員又是組織者的組織,而不是其中任何一個都為真的組織。要在圖表中視覺化,我想:

在此處輸入圖像描述

紅色區域是我想要請求的地方。

維恩圖不適合視覺化像 a_horse 這樣的連接操作評論

維恩圖不視覺化連接,而是設置聯合、相交或除外等操作。

他的連結來說明:

我認為,扭曲之處在於:維恩圖是視覺化目標的正確工具,但 SQLJOIN是錯誤的方法。您需要一個UNION(或等效的)作為查詢的核心。

標題和範例查詢這樣具有誤導性。更重要的是,您可以從以下內容開始:

SELECT * FROM ...

這會從所有連接的表中獲取所有列。也不是表達的目標:

我是版主或管理員的所有組織。

UNION

核心查詢是:

SELECT organization FROM admin_organization     WHERE user = 10
UNION
SELECT organization FROM moderator_organization WHERE user = 10

UNION. 不是JOIN。而不是UNION ALL- 我們不希望結果中出現重複的組織。

列名organization具有誤導性(恕我直言)。為了清楚起見,真的應該是這樣organization_id的。

生成的唯一 ID 集可能已經足夠了。為了用組織的更多(或所有)屬性(表的列organization)來充實它,現在我們JOIN來表:

SELECT *
FROM  (
  SELECT organization AS id FROM admin_organization WHERE user = 10
  UNION
  SELECT organization FROM moderator_organization WHERE user = 10
  ) x
JOIN   organization USING (id);

UNION僅在 ID 列上應用然後加入通常(大大)便宜。如果某些列的類型具有沒有相等運算符的數據類型,它甚至可能是必需的。比人們想像的更常見。看:

假設參照完整性,通過 FK 約束強制執行,連接中不會失去任何內容。

方便起見organization AS id,它在子查詢中添加了一個列別名USING (id)(沒有重複 ID 列的SELECT *表。organization

替代EXISTS

更短的等效項,也可以避免過度重複或刪除行:

SELECT *
FROM   organization o
WHERE  EXISTS (SELECT FROM admin_organization     WHERE user = 10 AND organization = o.id)
  OR  EXISTS (SELECT FROM moderator_organization WHERE user = 10 AND organization = o.id);

命名約定

具有描述性名稱的命名約定可以避免一些混亂和噪音。對所有三個都使用organization_id(或者org_id如果您更喜歡短名稱並且沒有歧義):admin_organization.organizationmoderator_organization.organizationorganization.id.

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