从“组合,任一内部连接”中获取结果

pau*_*l23 1 postgresql join database-design union

我有一种感觉,这肯定被问过多次,但我只是找不到解决方案,甚至可能因为难以解释而提出问题。

我们都知道内连接基本上给出了两个表的“交集”。因此多个内连接给出了所有表的交集。但是,我希望获得一个内部连接,该连接获得表 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
Run Code Online (Sandbox Code Playgroud)

然而,上面只会选择用户(ID 为 10)既是管理员又是组织者的组织,而不是其中任何一个都为真的组织。要在图表中可视化,我想:

在此处输入图片说明

红色区域是我想要请求的地方。

Erw*_*ter 5

维恩图不适合可视化连接操作,如 a_horse评论

维恩图不可视化连接,而是设置并集、相交或除外等操作。

和他的链接来说明:

我认为,扭曲是这样的:维恩图是可视化目标的正确工具,但 SQLJOIN是错误的方法。您UNION的查询的核心需要一个(或等效的)。

标题和示例查询具有误导性。更重要的是,你开始:

SELECT * FROM ...
Run Code Online (Sandbox Code Playgroud)

这会从所有连接的表中获取所有列。也不是表达的目标:

我是主持人或管理员的所有组织。

UNION

核心查询是:

SELECT * FROM ...
Run Code Online (Sandbox Code Playgroud)

UNION. 不是JOIN。而不是UNION ALL- 我们不希望结果中有重复的组织。

列名organization具有误导性(恕我直言)。organization_id为了清楚起见,真的应该是这样的。

由此产生的一组唯一 ID 可能已经足够了。为了用组织的更多(或全部)属性(表格的列)充实它organization现在我们JOIN到表格:

SELECT organization FROM admin_organization     WHERE user = 10
UNION
SELECT organization FROM moderator_organization WHERE user = 10
Run Code Online (Sandbox Code Playgroud)

UNION仅在 ID 列上申请然后加入通常(实质上)更便宜。如果某些列的类型具有没有相等运算符的数据类型,则它甚至可能是必需的。比人们想象的更常见。看:

假设参照完整性,使用 FK 约束强制执行,连接中不会丢失任何内容。

方便起见,它在子查询 ( organization AS id) 中添加了列别名,以便我们可以使用简化的连接条件USING (id),反过来,允许我们SELECT *在外部查询中使用简单的(现在正确的)来获取所有列organization没有重复 ID 列的表。

替代 EXISTS

更短的等价物也避免了行的过度重复或消除:

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);
Run Code Online (Sandbox Code Playgroud)

命名约定

具有描述性名称的命名约定可以避免一些混淆和噪音。使用organization_id(或者org_id,如果你喜欢短的名字并没有歧义)所有三种:admin_organization.organizationmoderator_organization.organization,和organization.id