SQL 与 Not exists 的双重否定

SQL double negation with Not exists

我有一个嵌套的 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 Does not exist the parts that are not supplied by 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 who supply every part"

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)
                  )

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

查询中"all"没有任何意义。这两个查询完全不同。

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

如果你知道每个供应商卖多少零件,知道有多少零件。比较这些值很容易。

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

不对,操作不等价。您要实现的目标相当于 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 被排除在结果集中,因为它是唯一销售未在部分 table 中列出的产品的产品。 此行的存在从最终结果集中排除了 RD2D。