Jmo*_*y38 4 postgresql database-design relational-division
我有两个表,外键来自 T1->T2,处于一对多关系。也就是说,表 T1 中的 1 个元组与 T2 中的 0..N 个元组相关联。
为了创建一个简单的例子,假设 T1 是汽车,而 T2 是一个缺陷表。因此,一辆汽车可以有 0..N 个缺陷,我们将这些缺陷作为整数存储在 T2 中。
我想仅从包含缺陷 i1和i2 的汽车中的那些汽车中选择 * 。
相反,执行 OR 非常简单:
SELECT * FROM cars AS T1
WHERE EXISTS (
SELECT imperfection FROM Imperfections as T2
WHERE T1.uid = T2.uid AND (imperfection = 1 OR imperfection = 2)
);
Run Code Online (Sandbox Code Playgroud)
我一直在尝试使用交集设置逻辑,但在这一点上,我想知道我是否过于复杂了。
您可以有两个单独的存在子句:
SELECT *
FROM cars AS T1
WHERE
EXISTS
(
SELECT * FROM Imperfections as T2
WHERE T1.uid = T2.uid AND imperfection = 1
)
AND EXISTS
(
SELECT * FROM Imperfections as T2
WHERE T1.uid = T2.uid AND imperfection = 2
);
Run Code Online (Sandbox Code Playgroud)
这意味着两个左半连接到您的 Imperfections 表,但如果您有关于 UID 和 Imperfection 的索引,这些应该是微不足道的。
在这种情况下,使用 WHERE EXISTS 比使用 JOIN 有两个优点。第一个是左半连接在第一次匹配后停止,因此它可以比连接更快(需要遍历所有记录)。第二个是,如果您不知何故没有良好的数据约束并且在 Imperfections 中有两个具有相同 UID 和 Imperfection 的记录,您最终可能会在主查询中返回重复的行。
在最简单的走最短的路
SELECT c.*
FROM
cars AS c
JOIN Imperfections as i1 ON c.uid = i1.uid AND i1.imperfection = 1
JOIN Imperfections as i2 ON c.uid = i2.uid AND i2.imperfection = 2
;
Run Code Online (Sandbox Code Playgroud)
(INNER) JOINs对存在本身的考验。
这成立 if (uid, imperfection)is UNIQUE,这在这里是合理的,但尚未定义。可能存在缺陷的子类型......那么你需要一个DISTINCTor GROUP BY。USING (uid)甚至会比ON c.uid = i1.uid. 届时,不完美将进入一个WHERE条款。
下一个想法与凯文在他的回答中描述的相同,所以我不会在这里包含它。