简体   繁体   中英

How to select distinct based on multiple values for one column

I feel this is a very easy task and I am grossly overthinking it. I have looked and looked nothing seems to answer my question. My question is simple, how do I select distinct on one column, based on multiple values of another column:

Table:

Customers Fruit
Bob Orange
Bob Apple
Sally Orange
Sally Lemon
Sam Lemon
Sam Apple
Tom Orange
Tom Lime

The table above shows a new line every time a customer purchases a fruit. How do I select distinct for customers who either purchased an (Orange AND Apple) OR (Orange AND Lemon).

The end result should only show: Bob and Sally.

Something like this?

SELECT Customers
FROM dbo.YourTable
GROUP BY Customers
HAVING (COUNT(CASE Fruit WHEN 'Orange' THEN 1 END) >= 1 AND COUNT(CASE Fruit WHEN 'Apple' THEN 1 END) >= 1)
    OR (COUNT(CASE Fruit WHEN 'Orange' THEN 1 END) >= 1 AND COUNT(CASE Fruit WHEN 'Lemon' THEN 1 END) >= 1);

Assuming you don't care if a user has all 3 you still want them returned. or if they have more than 2 but at least orange and one of the other 2.

Just using a simple join. Get those that are Orange and those that are either Apple or lemon--> join--> distinct.

SELECT Distinct A.Customers
FROM dbo.yourTable A
INNER JOIN dbo.yourTable B
 on A.Customer = B.Customer
WHERE A.Fruit = 'Orange'
  and B.Fruit in ('Apple','Lemon')

Assuming an index on dbo.yourTable.Fruit... should be pretty quick.

Use conditional aggregation:

SELECT Customer
FROM tablename
WHERE Fruit IN ('Orange', 'Apple', 'Lemon')
GROUP BY Customer
HAVING COUNT(CASE WHEN Fruit = 'Orange' THEN 1 END) > 0 -- the customer bought 'Orange' at least once
   AND COUNT(DISTINCT Fruit) > 1 -- the customer bought at least 2 of the 3 fruits

If you want to exclude the case that the customer has bought all 3 fruits:

SELECT Customer
FROM tablename
WHERE Fruit IN ('Orange', 'Apple', 'Lemon')
GROUP BY Customer
HAVING COUNT(CASE WHEN Fruit = 'Orange' THEN 1 END) > 0 -- the customer bought 'Orange' at least once
   AND COUNT(DISTINCT Fruit) = 2 -- the customer bought exactly 2 of the 3 fruits

A fun alternative using the underappreciated INTERSECT

SELECT Person FROM YourTable WHERE Fruit = 'Apple' 
INTERSECT -- INTERSECT discards duplicates
SELECT Person FROM YourTable WHERE Fruit = 'Orange'

UNION -- UNION also does an implicit DISTINCT

SELECT Person FROM YourTable WHERE Fruit = 'Lemon' 
INTERSECT 
SELECT Person FROM YourTable WHERE Fruit = 'Orange'

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