SQL选择存在子集的所有行
我确信这个问题有一个答案,但请容忍我,因为我是SQL新手,不知道如何提问 我有这样的数据(这纯粹是速记)。 这是在postgres数据库中SQL选择存在子集的所有行,sql,database,postgresql,relational-division,Sql,Database,Postgresql,Relational Division,我确信这个问题有一个答案,但请容忍我,因为我是SQL新手,不知道如何提问 我有这样的数据(这纯粹是速记)。 这是在postgres数据库中 table1 id value 1 111 1 112 1 113 2 111 2 112 2 116 3 111 3 122 3 123 4 126 5 123 5 125 6 111 6 112 6 116 table2 val
table1
id value
1 111
1 112
1 113
2 111
2 112
2 116
3 111
3 122
3 123
4 126
5 123
5 125
6 111
6 112
6 116
table2
value
111
112
116
我需要返回table1的id,其中table2中的所有值都存在于table1的值中。对于这个例子,我的查询将返回2和6
在SQL中有什么方法可以做到这一点吗?或者你能给我一个数据结构,让我得到这个结果吗?我能够改变任何一个表的结构,以适应最终获得这个结果的需要
非常感谢你。解决这个问题的办法就是救命。考虑一下这个演示:
CREATE TEMP TABLE table1(id int, value int);
INSERT INTO table1 VALUES
(1,111),(1,112),(1,113)
,(2,111),(2,112),(2,116)
,(3,111),(3,122),(3,123)
,(4,126)
,(5,123),(5,125)
,(6,111),(6,112),(6,116);
CREATE TEMP TABLE table2(value int);
INSERT INTO table2 VALUES
(111)
,(112)
,(116);
SELECT t1.id
FROM table1 t1
JOIN table2 t2 USING (value)
GROUP BY t1.id
HAVING count(*) = (SELECT count(*) FROM table2)
ORDER BY t1.id;
结果:
id
-----
2
6
返回table1
的所有ID,这些ID与table2
提供的所有值一起出现一次。适用于两个表中任意数量的行 如果重复行出现在
表1
中,请执行以下操作:
HAVING count(DISTINCT value) = (SELECT count(*) FROM table2)
更新另一种可能性:
SELECT t1.id
FROM (SELECT t1.id, t1.value
FROM table1 t1
JOIN table2 t2 USING (value)
GROUP BY t1.id, t1.value
ORDER BY t1.id) t1
GROUP BY t1.id
HAVING COUNT(*) = (SELECT COUNT(*) FROM table2)
如果使用EXPLAIN ANALYSE,我的答案的成本始终是893-900,即使是重复的行。在我看来,你想知道如何提出正确的问题,也需要付出同样多的代价。这里的神奇词语是“关系划分” 它是世纪年代的运营商之一,自那时以来,已经提出了几项变更。最近,有人提议将整个概念替换为 SQL没有显式的除法运算符。使用其他运算符有许多变通方法,最合适的方法取决于您的要求,包括精确除法或带余数的除法以及如何处理空除法。然后是常见的考虑因素:SQL产品和版本、性能、个人风格和品味等 以下几篇文章可以帮助您做出以下选择: 不存在(…不存在)是关系划分的标准解决方案:
SELECT DISTINCT id
FROM table1 t1
WHERE NOT EXISTS (
SELECT * FROM table2 t2
WHERE NOT EXISTS (
SELECT * FROM table1 t1x
WHERE t1x.value = t2.value
AND t1x.id = t1.id
)
)
;
在这种情况下,需要使用
DISTINCT
,因为我们无法访问具有id
s的域表,只能访问引用它的连接表t1
。在我看来@ErwinBrandstetter的答案已经是“拯救你的生命”。您是否介意接受它作为正确答案,或者对此答案的任何问题进行评论。请用各种方法查看此问题以解决此关系划分问题:此查询的成本可能低于Erwin的,但它不是正确的解决方案。如果OP的示例中有一行(7111)
,那么输出将包含id
7
,即使没有(7112)
和(7116)
行。你没想过要提到吗?@某天当:你是对的,它是密切相关的。相比之下,这个例子有点简化了。+1在关系划分的主题上是非常有用的切入点。