【问题标题】:SQL Select all rows where subset existsSQL选择存在子集的所有行
【发布时间】:2011-12-08 01:59:48
【问题描述】:

我确定这个问题有答案,但请耐心等待,因为我是 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
value
111
112
116

我需要返回 table1 的 id,其中 table2 中的所有值都存在于 table1 的值中。所以对于这个例子,我的查询将返回 2 和 6。

有没有办法在 SQL 中做到这一点?或者你能指导我使用一个数据结构来让我得到这个结果吗?我可以更改任一表的结构以适应获得此结果的最终需求

非常感谢。解决这个问题可以挽救生命。

【问题讨论】:

  • 在我看来,@ErwinBrandstetter 的回答确实已经“挽救了你的生命”。您能否介意接受它作为正确答案或对此答案的任何问题发表评论。
  • 查看这个问题,用各种方法解决这个关系划分问题:stackoverflow.com/questions/7364969/…

标签: sql database postgresql relational-division


【解决方案1】:

考虑这个演示:

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 提供的所有值一起出现一次。
适用于两个表中的任意数量的行。

如果table1 中可能出现重复行,请这样做:

HAVING count(DISTINCT value) = (SELECT count(*) FROM table2) 

【讨论】:

  • 你没想提this answer
  • @onedaywhen:你是对的,它密切相关。相比之下,这种情况稍微简化了一些。
【解决方案2】:

在我看来,您想知道如何提出正确的问题,这与任何事情一样多。这里的神奇词是“关系划分”。

它是Coddrelational algebra 中的运算符之一,此后提出了几种变体。最近,Chris Date 提议用image relations 替换整个概念。

SQL 没有明确的除法运算符。有许多使用其他运算符的解决方法,最合适的方法取决于您的要求,包括精确除法或除以余数以及如何处理空除数。然后是通常的考虑:SQL产品和版本、性能、个人风格和品味等。

这里有几篇文章可以帮助您做出这些选择:

On Making Relational Division Comprehensible

Divided We Stand: The SQL of Relational Division

【讨论】:

  • +1 关于关系划分主题的非常有用的切入点。
【解决方案3】:

更新另一种可能性:

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,即使重复行也是如此。

【讨论】:

  • 此查询的成本可能低于 Erwin 的,但它不是一个正确的解决方案。如果在 OP 的示例中有 (7, 111) 行,则输出将包含 id 7,即使没有 (7, 112)(7, 116) 行。
【解决方案4】:

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,因为我们无法访问带有ids 的 表,只能访问连接 表@ 987654324@指的是它。

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    相关资源
    最近更新 更多