这听起来很愚蠢。
所以2个表ORDER和ORDERDETAILs
ORDER_ID ITEM_NAME
======== =========
111 Paper
111 Toner
222 Paper
333 Pencils
我只想查询Order_ID,其中ITEM_Name是Paper
所以例如我的查询结果应该是
ORDER_ID ITEM_NAME
======== =========
222 Paper
我不希望ORder_ID具有与之相关的其他Item。我只想要ORDERID是唯一的ITEM_Name是Paper。
如果你想要只有纸质的订单ID,我建议使用group by
和having
子句:
select od.Order_Id
from OrderDetails od
group by od.Order_Id
having sum(case when od.Item_Name = 'Paper' then 1 else 0 end) > 0 and
sum(case when od.Item_Name <> 'Paper' then 1 else 0 end) = 0
having
条款有两个条件。第一个计算将Paper
作为项目的订单的行数。 > 0
说至少需要一个。第二个计算没有纸张的行数。 = 0
说没有必要。
这也可以写成:
having sum(case when od.Item_Name = 'Paper' then 1 else 0 end) = count(*)
即订单的所有商品均为“纸质”。
我喜欢这种方法,因为它非常通用。您可以轻松扩展它包括剪刀和岩石。或者获得有纸张但没有岩石的订单,等等。
SELECT OrderDetails.*
FROM OrderDetails
WHERE ITEM_Name = 'Paper'
AND Order_ID NOT IN (SELECT Order_ID FROM OrderDetails WHERE ITEM_Name <> 'Paper')
在这一个中,您选择item_name ='Paper'的所有项目。然后排除他们有一行<>'Paper'的所有订单
候补:
如果我们可以假设Item_Name对于每个订单都是唯一的,那么(至少在MS SQL Server中)您可以这样做:
;with NumberOfRows as
(
SELECT COUNT(1) as TotalRows, Order_ID
FROM OrderDetails
GROUP BY Order_ID
)
SELECT OrderDetails.*
FROM OrderDetails
INNER JOIN NumberOfRows
ON NumberOfRows.Order_ID = OrderDetails.OrderID
AND NumberOfRows.TotalRows = 1
WHERE OrderDetails.Item_Name = 'Paper'
作为另一种选择:
select OrderDetails1.*
from OrderDetails as OrderDetails1
LEFT JOIN OrderDetails OrderDetails2
ON OrderDetails1.Order_ID = OrderDetails2.Order_ID
AND OrderDetails2.ITEM_Name <> 'Paper'
Where ITEM_Name = 'Paper'
AND OrderDetails2.Order_ID IS NULL
在最后一个订单中,您将获得所有订单并重新加入自己的第二行,而不是纸张。然后排除连接成功的所有订单。如果订单详细信息表具有独特的内容(如行ID),这将更容易理解。