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)既是管理员又是组织者的组织,而不是其中任何一个都为真的组织。要在图表中可视化,我想:
红色区域是我想要请求的地方。
维恩图不适合可视化连接操作,如 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.organization,moderator_organization.organization,和organization.id。
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |