我确信这个问题有一个答案,但请耐心等待我,因为我是SQL新手,不知道如何提问。
我有这样的数据(这只是简单的简写)。 这是一个postgres db。
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中执行此操作?或者你可以引导我到一个允许我得到这个结果的数据结构吗?我可以更改任一表的结构,以满足获得此结果的最终需要
非常感谢你。对此的答案是节省生命。
答案 0 :(得分:6)
考虑一下这个演示:
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,其中table2
提供的所有值均为。{
适用于两个表中的任意行数。
如果table1
中出现重复的行,请执行以下操作:
HAVING count(DISTINCT value) = (SELECT count(*) FROM table2)
答案 1 :(得分:3)
在我看来,你想知道如何提出正确的问题。这里的魔术词是“关系分裂”。
它是Codd的relational algebra中的运算符之一,自此以后提出了一些变体。最近,Chris Date建议用image relations替换整个概念。
SQL没有明确的除法运算符。有许多使用其他运算符的变通方法,最合适的将取决于您的要求,包括对余数的精确除法或除法以及如何处理空除数。然后有通常的考虑因素:SQL产品和版本,性能,个人风格和品味等。
以下是一些可以帮助您做出这些选择的文章:
答案 2 :(得分:1)
更新另一种可能性:
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 ANALYZE ,我的答案费用总是893-900,即使重复行也是如此。
答案 3 :(得分:0)
NOT EXISTS(... NOT EXISTS)是关系部门的标准解决方案:
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
的域表,只能访问联结表t1
引用它。