How do I find groups of rows where all rows in each group have a specific column value
-
22-04-2021 - |
Вопрос
Sample data:
ID1 ID2 Num Type
---------------------
1 1 1 'A'
1 1 2 'A'
1 2 3 'A'
1 2 4 'A'
2 1 1 'A'
2 2 1 'B'
3 1 1 'A'
3 2 1 'A'
Desired result:
ID1 ID2
---------
1 1
1 2
3 1
3 2
Notice that I'm grouping by ID1 and ID2, but not Num, and that I'm looking specifically for groups where Type = 'A'. I know it's doable through a join two queries on the same table: one query to find all groups that have a distinct Type, and another query to filter rows with Type = 'A'. But I was wondering if this can be done in a more efficient way.
I'm using SQL Server 2008, and my current query is:
SELECT ID1, ID2
FROM (
SELECT ID1, ID2
FROM T
GROUP BY ID1, ID2
HAVING COUNT( DISTINCT Type ) = 1
) AS SingleType
INNER JOIN (
SELECT ID1, ID2
FROM T
WHERE Type = 'A'
GROUP BY ID1, ID2
) AS TypeA ON
TypeA.ID1 = SingleType.ID1 AND
TypeA.ID2 = SingleType.ID2
EDIT: Updated sample data and query to indicate that I'm grouping on two columns, not just one.
Решение
SELECT ID1, ID2
FROM MyTable
GROUP BY ID1, ID2
HAVING COUNT(Type) = SUM(CASE WHEN Type = 'A' THEN 1 ELSE 0 END)
Другие советы
There are two alternatives that don't require the aggregation (but do require distinct)
ANTI-JOIN
SELECT DISTINCT t1.ID1, t1.ID2
FROM
table t1
LEFT JOIN table t2
ON t1.ID1 = t2.ID1
and t1.Type <> t2.Type
WHERE
t1.Type = 'A'
AND
t2.ID1 IS NULL
See it working at this data.se query Sample for 9132209 (Anti-Join)
NOT EXISTS
SELECT DISTINCT t1.ID1, t1.ID2
FROM
table t1
WHERE
t1.Type = 'A'
AND
NOT EXISTS
(SELECT 1
FROM table t2
WHERE t1.ID1 = t2.ID1 AND Type <> 'A')
See it working at this data.se query Sample for 9132209 Not Exists