Как найти группы строк, где все строки в каждой группе имеют определенное значение столбца

Образец данных:

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'

Желаемый результат:

ID1   ID2
---------
1     1
1     2
3     1
3     2

Обратите внимание, что я группирую по ID1 и ID2, но не по Num, и что я специально ищу группы, где Type = 'A'. Я знаю, что это выполнимо с помощью объединения двух запросов к одной таблице: один запрос для поиска всех групп с различным типом и другой запрос для фильтрации строк с типом = 'A'. Но мне было интересно, можно ли это сделать более эффективным способом.

Я использую SQL Server 2008, и мой текущий запрос:

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: обновлен пример данных и запрос, чтобы указать, что я группирую по двум столбцам, а не только по одному.


person khaledh    schedule 03.02.2012    source источник
comment
Как выглядит ваш текущий запрос?   -  person N West    schedule 03.02.2012


Ответы (2)


Есть две альтернативы, которые не требуют агрегации (но требуют отдельных)

ЗАЩИТА ОТ ПРИСОЕДИНЕНИЯ

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

Посмотрите, как это работает в этом примере запроса data.se для 9132209 (анти-объединение)

НЕ СУЩЕСТВУЕТ

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

Посмотрите, как это работает в этом примере запроса data.se для 9132209 Not Exists

person Conrad Frix    schedule 03.02.2012

person    schedule
comment
Спасибо, Бассам, но у меня возникли проблемы с выполнением этого запроса, поскольку в моих реальных данных ID1 — это не просто один столбец, поэтому он жалуется, что для функции COUNT требуется 1 аргумент. Я обновлю свои образцы данных. - person khaledh; 03.02.2012
comment
@JNK Я уверен, что ты бы поймал это сам, с двойным дублем :D - person Bassam Mehanni; 03.02.2012
comment
@BassamMehanni - возможно, но я думаю, что этот ответ правильный. - person JNK; 03.02.2012
comment
@khaledh попробуйте заменить Count (ID1) на COUNT (Type), он должен быть фактически таким же, потому что он должен быть эквивалентен количеству строк. - person Bassam Mehanni; 03.02.2012
comment
@BassamMehanni Работает отлично! Спасибо. - person khaledh; 03.02.2012
comment
@khaledh отлично!! рад, что могу помочь! - person Bassam Mehanni; 03.02.2012
comment
Незначительная деталь: чтобы вопрос соответствовал написанному в настоящее время, я думаю, что оба экземпляра ID1 следует заменить на ID1, ID2. Это смутило меня на мгновение, поэтому я решил упомянуть об этом. - person Ilmari Karonen; 04.02.2012