【问题标题】:SQL double negation with Not exists不存在的 SQL 双重否定
【发布时间】:2015-11-20 18:10:04
【问题描述】:

我有一个嵌套的 Not Exists,并且想知道它是否是双重否定。如果我删除两个否定,如果它是等效的查询?

Suppliers(sid: integer, sname: string, address: string)
Parts(pid: integer, pname: string, color: string)
Catalog(sid: integer, pid: integer, cost: real)

SQL 翻译:“C.Sid for which doesn't exist 不存在 C.Sid 的部分”

SELECT C.sid
FROM Catalog C
WHERE NOT EXISTS (SELECT P.pid
                  FROM Parts P
                  WHERE NOT EXISTS (SELECT C1.sid
                                    FROM Catalog C1
                                    WHERE C1.sid = C.sid
                                    AND C1.pid = P.pid)
                  )

删除的否定:“提供每个部分的 C.Sid”

SELECT C.sid
FROM Catalog C
WHERE EXISTS (SELECT P.pid
                  FROM Parts P
                  WHERE EXISTS (SELECT C1.sid
                                    FROM Catalog C1
                                    WHERE C1.sid = C.sid
                                    AND C1.pid = P.pid)
                  )

【问题讨论】:

  • 那行不通,你不是在处理“每个部分”,只是“存在一个部分”

标签: sql logic


【解决方案1】:

不,操作不等价。您试图实现的目标相当于 SQL 中的 algebra division operation

这是一个SQLFiddle,您可以在其中测试以下查询:

第一个:

SELECT * FROM Catalog C
WHERE NOT EXISTS (SELECT P.pid FROM Part P
                  WHERE NOT EXISTS (SELECT C1.sid FROM Catalog C1
                                    WHERE C1.sid = C.sid
                                    AND C1.pid = P.pid) );

sid pid
1   1
1   2
2   1
2   2

替代方案(您可以看到现在的结果是等效的):

SELECT * FROM Catalog C
WHERE EXISTS (SELECT P.pid FROM Part p
              WHERE EXISTS (SELECT C1.sid FROM Catalog C1
                            WHERE C1.sid = C.sid
                              AND C1.pid = P.pid) );

sid pid
1   1
1   2
2   1
2   2
3   1
3   3

还有一个经典的数据库课程练习:

-- Suppliers for which doesn't exists any part that they doesn't provide.
SELECT * FROM supplier S
WHERE NOT EXISTS ( SELECT * FROM part P
                   WHERE NOT EXISTS ( SELECT * FROM catalog C
                                      WHERE S.sid = C.sid
                                        AND P.pid = C.pid ) );

sid name
1   "Dath Vader"
2   "Han Solo"

剖析上述查询的一部分可能会让您更好地了解查询中涉及的逻辑。

SELECT * FROM part P
WHERE NOT EXISTS ( SELECT * FROM catalog C
                   WHERE P.pid = C.pid
                     AND C.sid = 3); -- R2D2 Here!

pid name
2   "Laser Gun"

R2D2 被排除在结果集中,因为它是唯一一个销售未在零件表中列出的产品的产品。 此行的存在将 RD2D 从最终结果集中排除。

【讨论】:

    【解决方案2】:

    您的第二个查询是C.Sid,他提供了目录中的零件。

    查询中没有“全部”的含义。这两个查询完全不同。

    【讨论】:

      【解决方案3】:

      不确定您的问题是否只是教育性的,或者您正在寻求更好的方法来解决您的问题。

      如果您知道每个供应商销售了多少零件,并且知道有多少零件。很容易比较这些值。

      SELECT C.Sid
      FROM Catalog C
      GROUP BY C.Sid
      HAVING COUNT(pid) = (SELECT COUNT(P.pid)
                           FROM Parts P)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 2021-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-30
        相关资源
        最近更新 更多