存在还是不存在查询误解?

时间:2016-02-14 22:18:42

标签: sql database database-design relational-database relational-algebra

考虑产品数据库的以下模式:

  • Parts(pid,pname)
  • Suppliers(sid,sname)
  • Catalog(sid,pid)
sid中的{p> Catalog是外键,Suppliers中的引用pidCatalog是外键并引用Parts表。 (s1, p1)表格中的Catalog表示供应商s1生成p1

如果我想查找某些供应商未提供的Parts详情,我们该如何做?我读了一些如下部分:

SELECT *
FROM parts P
WHERE ....... (SELECT S.sid 
               FROM suppliers 
                WHERE .....
                       (SELECT * 
                        FROM catalog C 
                        WHERE s.sid = C.sid AND P.pid = C.pid))

我的问题是通过 - 为什么一开始?我们使用存在而在第二......我们使用不存在?

2 个答案:

答案 0 :(得分:3)

那么简单吗?如果没有,请使用我的示例表并指定您的预期输出:

variablename = foo, variablename2 = bar

结果

DECLARE @Parts TABLE(pid INT, pname VARCHAR(100));
DECLARE @Suppliers TABLE(sid INT, sname VARCHAR(100));
DECLARE @Catalog TABLE(pid INT, sid INT);

INSERT INTO @Parts VALUES(1,'Part 1'),(2,'Part 2'),(3,'Part 3'),(4,'Part 4');
INSERT INTO @Suppliers VALUES(1,'Suppl 1'),(2,'Suppl 2'),(3,'Suppl 3');
INSERT INTO @Catalog VALUES(1,1),(1,3) --part 1 from two suppliers
                          ,(2,1)       --part 2 from one supplier
                                       --part 3 no supplier
                                       --part 4 no supplier

--Get all parts *that not supplied by some suppliers*
SELECT * 
FROM @Parts AS p 
WHERE p.pid NOT IN(SELECT c.pid FROM @Catalog AS c) 

编辑:与#34;你的"达到了同样的目标。查询,但这会更糟糕:

此查询正在查找部件,其中没有供应商 在"目录"中有条目。我必须承认,这有点像家庭作业: - )

pid pname
3   Part 3
4   Part 4

答案 1 :(得分:3)

  

如果我想查找某些供应商未提供的Parts详情,我们该如何做?

如果您需要"有供应商不提供该部件的部件的详细信息"那么您的查询EXISTS然后NOT EXISTS是正确的。

  

我的问题是通过 - 为什么一开始?我们使用存在而在第二......我们使用不存在?

我将解释为什么有供应商不提供该部分的部件的详细信息"可以提供您的查询。 (使用EXISTS然后NOT EXISTS。)

表格中包含将某些谓词(语句模板)转换为真正的命题(语句)的行:

  • Parts"部分P.pid命名为P.pname"
  • Suppliers"供应商S.sid被命名为S.sname"
  • Catalog"供应商C.sid提供部分C.pid"

您需要为结果表达谓词。您希望P.pid - P.pname行从中做出真正的声明:

    "part P.pid is named P.pname"
AND EXISTS S.sid ["supplier S.sid is named something"
        AND NOT "supplier S.sid supplies part P.pid"]

但是我们必须用给定的谓词(加上条件和逻辑运算符)来表达这个谓词,以便DBMS可以计算满足它的行:

    "part P.pid is named P.pname"
AND EXISTS S.sid [EXISTS S.sname "supplier S.sid is named S.sname"
        AND NOT EXISTS C.sid, C.pid [
                "supplier C.sid supplies part P.pid" AND C.sid = S.sid AND C.pid = P.pid]]

现在转换为SQL:

  • T 的初始谓词变为FROM T
  • AND T 的谓词变为JOIN T
  • AND 条件变为WHERE condition ON condition
  • 最外面的EXISTS 已删除的列变为SELECT kept columns
  • 其他EXISTS T [谓词T ]的所有列都变为EXISTS ( T {{1} }

)

PS 您的问题的原始"某些供应商未提供的部件的详细信息"不清楚/含糊不清。这可能意味着SELECT * FROM Parts P WHERE EXISTS (SELECT S.sid FROM Suppliers S WHERE NOT EXISTS (SELECT 1 FROM Catalog C WHERE C.sid = S.sid AND C.pid = P.pid)) - P.id对,其中:

  1. "所有供应商都不提供这些部件" (解释与您的SQL一致)
  2. "部件不供应(由任何供应商提供)" (解释与Shnugo's answer
  3. 中的两个SQL版本一致
  4. "这些部件没有多个供应商"

    P.pname
  5. 如果你有SELECT * FROM Parts P WHERE NOT EXISTS (SELECT * FROM Catalog C1 JOIN Catalog C2 ON C1.sid <> C2.sid AND C1.pid = P.pid AND C2.pid = P.pid) 1-4和Parts 1-3,那么上面给出了三个不同的答案:

    Suppliers

    PPS 上述逻辑公式为:

    INSERT INTO Catalog VALUES (1,1),(2,1),(2,2),(3,1),(3,2),(3,3);