2015-04-23 3 views
0

Я чувствую, что я должен быть в состоянии получить это, и у меня просто есть мозговой пердит. Я упростил проблему в следующем примере:Найти группы, которые не содержат всех записей

DECLARE @A TABLE (ID int); 
DECLARE @B TABLE (GroupID char(1), ID int); 

INSERT @A VALUES (1); 
INSERT @A VALUES (2); 
INSERT @A VALUES (3); 

INSERT @B VALUES ('X', 1); 
INSERT @B VALUES ('X', 2); 
INSERT @B VALUES ('X', 3); 

INSERT @B VALUES ('Y', 1); 
INSERT @B VALUES ('Y', 2); 

INSERT @B VALUES ('Z', 1); 
INSERT @B VALUES ('Z', 2); 
INSERT @B VALUES ('Z', 3); 
INSERT @B VALUES ('Z', 4); 

Таким образом, таблица A содержит набор некоторых записей. Таблица B содержит несколько копий набора, содержащегося в A с идентификаторами группы. Но в некоторых из этих групп может отсутствовать одна или несколько записей набора. Я хочу найти группы, в которых отсутствуют записи. Таким образом, в приведенном выше примере, мои результаты должны быть:

GroupID 
------- 
Y 

Но по какой-то причине я не могу обернуть мою голову вокруг этого, сегодня. Любая помощь будет оценена по достоинству.

+0

Этот вид требования просто автоматически запускает ГДЕ НЕ СУЩЕСТВУЕТ ответ в мой мозг .... –

ответ

2

Awesome чехол для relational division! (Here's a must-read blog post about it)

SELECT DISTINCT b1.GroupID 
FROM @B b1 
WHERE EXISTS (
    SELECT 1 
    FROM @A a 
    WHERE NOT EXISTS (
    SELECT 1 
    FROM @B b2 
    WHERE b1.GroupID = b2.GroupID 
    AND b2.ID = a.ID 
) 
); 

Как это прочесть?

Я хочу, чтобы в @B все различны GroupIDs, для которых есть запись в @A, для которых не существует запись в @B с той же @A.ID

На самом деле, это «остаток» реляционного деления.

+0

D 'ой! Ага. Это был синтаксис, который я пытался создать. Но по какой-то причине это просто не пришло ко мне. (Пожалуй, пора отдохнуть.) Спасибо всем! – DeadZone

+0

@DeadZone: проблем нет. Я думаю, что большинство людей (включая меня) должны смотреть каждый раз, когда нам это нужно. Однако помните термин «реляционное разделение». Это легко Google –

+0

Да, я никогда не видел этот термин раньше. Мне придется потратить немного времени на проверку этой страницы вики. :) – DeadZone

2

попробовать это

SELECT GroupID ,COUNT(GroupID) 
    FROM @a INNER JOIN @b 
    ON @[email protected] 
    GROUP BY GroupID 
    HAVING COUNT(GroupID)<(SELECT count(*) FROM @a) 
0

Это даст вам все комбинации, которые отсутствуют.

select FullList.* 
from (select distinct a.ID, 
      b.GroupId 
      from @A a 
      cross join @B b) FullList 
left join @B b 
on FullList.ID = b.ID 
and FullList.GroupID = b.GroupID 
where b.ID is null 

Ответ на ваш вопрос будет просто то же самое, но с первой строки:

select distinct FullList.GroupID 
0

Это даст вам все комбинации, которые отсутствуют.

select FullList.* 
    from (select distinct a.ID, 
         b.GroupId 
     from @A a 
     cross join (select distinct db.GroupId from @B db) b 
     ) as FullList 
    left join @B b 
    on FullList.ID = b.ID 
    and FullList.GroupID = b.GroupID 
    where b.ID is null 

Ответ на ваш вопрос будет просто то же самое, но с первой строки:

select distinct FullList.GroupID 
Смежные вопросы