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

时间:2011-11-10 01:06:11

标签: sql sql-server sql-server-2008

我有两个看起来像这样的表:

公司

  SN         SNAME  Stat   City
+----------+-------+----+--------+
| S1       | Smith | 20 | London |
| S2       | Jones | 10 | Paris  |
| S3       | Blake | 30 | Paris  |
| S4       | Clark | 20 | London |
| S5       | Adams | 30 | Athens |
+----------+-------+----+--------+

装运

 SN    PN   QTY
+----+----+-----+
| S1 | P1 | 300 |
| S1 | P2 | 200 |
| S1 | P3 | 400 |
| S1 | P4 | 200 |
| S1 | P5 | 100 |
| S1 | P6 | 100 |
| S2 | P1 | 300 |
| S2 | P2 | 400 |
| S3 | P2 | 200 |
| S4 | P2 | 200 |
| S4 | P4 | 300 |
| S4 | P5 | 400 |
+----+----+-----+

我找到了以下内容:

  

列出供应商S2提供的至少所有零件(PN)的供应商的供应商名称(SNAME)。

换句话说,我需要列出所有那些至少发货P1和P2的供应商,但显然我的查询需要更多地关注手头的问题。

我很确定我必须使用某种形式的NOT EXISTS - 也许双重不存在,才能实现这一点。我尝试将Shipment表自行连接到自身 - 但我无法理解除了检查出现在PN for S2中的任何项目之外如何检查它,而是检查以确保S2的所有部分都在在结果中包含名称之前列出。

2 个答案:

答案 0 :(得分:1)

您是否可以使用嵌套的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销售的东西时,他们才会被退回。

答案 1 :(得分:1)

我使用Common Table Expression来实现这一目标:

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