從“組合,或者內部連接”中獲取結果
我有一種感覺,這一定被問過很多次了,但我就是找不到解決方案,甚至找不到可能是因為難以解釋的問題。
我們都知道內連接基本上給出了兩個表的“交集”。因此,多個內連接給出了所有表的交集。但是,我希望獲得一個內部連接,該連接獲得表 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 這樣的連接操作評論:
維恩圖不視覺化連接,而是設置聯合、相交或除外等操作。
他的連結來說明:
我認為,扭曲之處在於:維恩圖是視覺化目標的正確工具,但 SQL
JOIN
是錯誤的方法。您需要一個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.organization
、moderator_organization.organization
和organization.id
.