SQL:确保根据一组行检查所有行

SQL:确保根据一组行检查所有行,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有两张像这样的桌子: 供应商 运输 我有以下发现: 列出至少装运供应商S2提供的所有零件PN的供应商名称SNAME 换句话说,我需要列出所有至少装运P1和P2的供应商,尽管我的查询显然需要更多地关注手头的问题 我很确定我必须使用某种形式的notexists,也许是double notexists,来实现这一点。我尝试将装运表自联接到自身,但除了检查S2 PN中出现的任何项目之外,我不明白如何进行自联接,而是在结果中包含名称之前检查以确保S2的所有部分都在列表中。是否可以使用嵌套的select语

我有两张像这样的桌子:

供应商 运输 我有以下发现:

列出至少装运供应商S2提供的所有零件PN的供应商名称SNAME

换句话说,我需要列出所有至少装运P1和P2的供应商,尽管我的查询显然需要更多地关注手头的问题


我很确定我必须使用某种形式的notexists,也许是double notexists,来实现这一点。我尝试将装运表自联接到自身,但除了检查S2 PN中出现的任何项目之外,我不明白如何进行自联接,而是在结果中包含名称之前检查以确保S2的所有部分都在列表中。

是否可以使用嵌套的select语句来优化结果

例如:

SELECT SNAME FROM Supplier
INNER JOIN Shipment ON Supplier.SN = Shipment.SN
WHERE Shipment.PN IN (SELECT PN FROM Shipment WHERE SN = S2)
这样,零件PN仅限于S2销售的零件

已编辑将语句更改为

Shipment.PN IN (SELECT PN FROM Shipment WHERE SN = S2)

现在,即使他们出售了所有东西中的一种,也只有在他们至少出售了S2出售的东西时才会被退回。

我使用了一个常用的表表达式来实现这一点:

--CTE will contain records from the Supplier you are looking to check against
WITH desiredSN AS
(
   SELECT s.SN, s.PN 
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)
--SELECT will join all other shippers with each record of your Supplier S2 here
SELECT s.SN
FROM Shipment AS s
INNER JOIN desiredSN AS d ON s.PN = d.PN
WHERE s.SN != 'S2'
GROUP BY s.SN
--Having ensures that the count of your old supplier matches
--the number a potential supplier overlaps with
HAVING COUNT(1) =
(
   SELECT COUNT(1)
   FROM desiredSN AS d
)
如果不想使用CTE,可以改用子查询:

SELECT s.SN
FROM Shipment AS s
INNER JOIN 
(
   SELECT s.SN, s.PN
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)
AS d ON s.PN = d.PN
WHERE s.SN != 'S2'
GROUP BY s.SN
HAVING COUNT(1) =
(
   SELECT COUNT(1)
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)

这似乎给了我每个至少销售S2也销售的部件的人,但没有给我那些至少销售S2销售的所有部件的人。这个问题的结果应该只有S1,因为只有S1同时销售P1和P2,而P1和P2是S2销售的零件。P3和P4仅销售S2销售的两个部件中的一个,但不能同时销售这两个部件。您可能可以进一步限制嵌套的select语句,并添加一个参数:shipping.PN=select PN FROM shipping,其中SN=S2和shipping.PN在P1、P2、P3、P4、P5中,这应首先验证供应商是否具有S2具有的所有值,然后它应该返回任何其他PN值。这是基于SQL自下而上读取参数,然后向下过滤以确保PN在限制范围内,然后验证这些PN是否等于S2的所有值。不幸的是,我认为不允许我们像P1、P2、P3、P4、P5那样离散地写出PN列表。它似乎也没有重新调整正确的结果——它现在只返回琼斯S2。是否有一种方法可以实现不存在的使用?我有一种感觉,这就是他在这里要做的,就他的想法来说,最简单的方式做它,虽然我肯定喜欢你的方式更好基本上排除了S2集合中不存在每个零件号的所有SNs。您的查询仍将返回一个供应商,该供应商只提供S2中的一个项目,in只要求它匹配一个项目,而不是所有项目。我在回答中为您添加了一个非CTE版本的查询。
--CTE will contain records from the Supplier you are looking to check against
WITH desiredSN AS
(
   SELECT s.SN, s.PN 
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)
--SELECT will join all other shippers with each record of your Supplier S2 here
SELECT s.SN
FROM Shipment AS s
INNER JOIN desiredSN AS d ON s.PN = d.PN
WHERE s.SN != 'S2'
GROUP BY s.SN
--Having ensures that the count of your old supplier matches
--the number a potential supplier overlaps with
HAVING COUNT(1) =
(
   SELECT COUNT(1)
   FROM desiredSN AS d
)
SELECT s.SN
FROM Shipment AS s
INNER JOIN 
(
   SELECT s.SN, s.PN
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)
AS d ON s.PN = d.PN
WHERE s.SN != 'S2'
GROUP BY s.SN
HAVING COUNT(1) =
(
   SELECT COUNT(1)
   FROM Shipment AS s
   WHERE s.SN = 'S2'
)