SQL根据条件忽略行

问题描述 投票:0回答:2

这听起来很愚蠢。

所以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。

sql where
2个回答
0
投票

如果你想要只有纸质的订单ID,我建议使用group byhaving子句:

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

即订单的所有商品均为“纸质”。

我喜欢这种方法,因为它非常通用。您可以轻松扩展它包括剪刀和岩石。或者获得有纸张但没有岩石的订单,等等。


0
投票
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),这将更容易理解。

© www.soinside.com 2019 - 2024. All rights reserved.