简体   繁体   中英

SQL ignore rows based on criteria

This is going to sound stupid.

So 2 tables ORDER and ORDERDETAILs

ORDER_ID      ITEM_NAME
========      =========
111           Paper
111           Toner
222           Paper
333           Pencils

I want to query only Order_ID's were the ITEM_Name is Paper

so for instance my query only result should be

ORDER_ID      ITEM_NAME
========      =========
222           Paper

I don't want ORder_ID's that have other Item's related to it. I only want ORDERID's were the the only ITEM_Name is Paper.

If you want order ids that are only paper, I would recommend using group by and a having clause:

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

The having clause has two conditions. The first counts the number of rows for an order that have Paper as an item. The > 0 says that there needs to be at least one. The second counts the number of rows that do not have paper. The = 0 says that there needs to be none.

This can also be written as:

having sum(case when od.Item_Name = 'Paper' then 1 else 0 end) = count(*)

ie All the items for the order are "Paper".

I like this method because it is very general. You can readily extend it to include scissors and rocks. Or to get orders that have paper, but no rocks, and so on.

I think that I am got your problem, but I am not sure kk.

If you wanna select a field in a table:

SELECT ORDER_ID FROM tablesname WHERE ITEM_NAME = 'Paper';

If you wanna select a field from other table, you should to make a relationship between them.

Example: https://www.sqlshack.com/learn-sql-types-of-relations/

If you want to retrieve only the order_ids:

select DISTINCT(ORDER_ID) 
from orderdetails
where ITEM_NAME='PAPER'
AND ORDER_ID NOT IN 
(SELECT DISTINCT(ORDER_ID) FROM ORDERDETAILS WHERE ITEM_NAME!='PAPER')

If you want all the columns from the order:

select *
from orderdetails
where ITEM_NAME='PAPER'
AND ORDER_ID NOT IN 
(SELECT DISTINCT(ORDER_ID) FROM ORDERDETAILS WHERE ITEM_NAME!='PAPER')
SELECT OrderDetails.*
FROM OrderDetails
WHERE ITEM_Name = 'Paper'
AND Order_ID NOT IN (SELECT Order_ID FROM OrderDetails WHERE ITEM_Name <> 'Paper')

In this one, you select all items where item_name = 'Paper'. Then exclude all orders where they have a line that <> 'Paper'

Alternates:

If we can assume that the Item_Name is unique for each order, then (at least in MS SQL Server) you could do:

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

As another option:

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

In this last one, you get all the orders and join back onto themselves where they have a 2nd line that is not paper. Then Exclude all of the orders where the join was successful. This would be easier to understand if the order details table had something unique (like a line id).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM