How do I find groups of rows where all rows in each group have a specific column value

StackOverflow https://stackoverflow.com/questions/9132326

  •  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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top