2014-08-29 2 views
-1

Мне нужна помощь с SQL-запросом, над которым я работаю. Вот упрощенная версия данных, с которыми я работаю. У меня есть 3 таблицы:Сложный запрос сервера sql

Контакты:

- ContactID 
- ContactName 

Материалы:

- SubmissionID 
- ContactID 
- SubmissionTypeID 

SubmissionTypes:

- SubmissionTypeID 
- SubmissionType 

Мне нужно вернуть все контакты (присоединено к Submissions по адресу ContactID), где есть SubmissionTypeIDs, которые соответствуют списку SubmissionTypeIDs. Сложная часть заключается в том, что мне нужны только результаты, в которых у контакта есть запись с сообщением SubmissionTypeID, которая соответствует каждому из значений в списке. Так, например, если бы я имел эти данные:

Contacts 
---------------- 
1 | Jim Johnson 
2 | Sally Anderson 

SubmissionTypes 
---------------------- 
1 | Contact Form 
2 | Request Form 
3 | Generic Form 

Submissions 
---------------------- 
1 | 1 | 1 
2 | 1 | 2 
3 | 2 | 1 

Если мои SubmissionTypeID значения 1 и 2, я хочу, чтобы получить следующие результаты:

Jim Johnson | Contact Form 
Jim Johnson | Request Form 

Я не хотел бы см. Салли Андерсон, потому что у нее нет записи в материалах для обоих значений.

Я предполагаю, что есть несколько способов сделать это. Я рад видеть ваши идеи.

Спасибо!

ответ

1

Один из способов с INTERSECT:

select c.contactname, t.submissiontype 
    from contacts c 
    join submissions s 
    on c.contactid = s.contactid 
    join submissiontypes t 
    on s.submissiontypeid = t.submissiontypeid 
    join (select c.contactid 
      from contacts c 
      join submissions s 
      on c.contactid = s.contactid 
     where s.submissiontypeid = 1 
     intersect 
     select c.contactid 
      from contacts c 
      join submissions s 
      on c.contactid = s.contactid 
     where s.submissiontypeid = 2) v 
    on c.contactid = v.contactid 
where s.submissiontypeid in (1, 2) 

Fiddle:http://sqlfiddle.com/#!6/9ee4e/2/0

Вы можете также COUNT, где равно 2 (у вас есть 2 значения вы проверяете для):

select c.contactname, t.submissiontype 
    from contacts c 
    join submissions s 
    on c.contactid = s.contactid 
    join submissiontypes t 
    on s.submissiontypeid = t.submissiontypeid 
    join (select c.contactid 
      from contacts c 
      join submissions s 
      on c.contactid = s.contactid 
     where s.submissiontypeid in (1, 2) 
     group by c.contactid 
     having count(distinct s.submissiontypeid) = 2) v 
    on c.contactid = v.contactid 
where s.submissiontypeid in (1, 2) 

Fiddle:http://sqlfiddle.com/#!6/9ee4e/1/0

+0

в зависимости от других ограничений, 'имея подсчет (*) = 2', возможно, необходимо будет' имея граф (отличный submissiontypeid) = 2'. +1 для 'intersect'. – Laurence

+0

@ Лоуренс согласился, как правило, я бы делал без отдельного по умолчанию, но я только что отредактировал его, потому что, вероятно, есть приличный шанс, что у контакта может быть более одного представления того же типа. –

1

Вот сложный способ использования двойного отрицания.

declare @list table (SubmissionTypeID int not null primary key); 

insert into @list values (1), (2); -- values to search for. 

with c as (
    select 
     c.ContactID, 
     c.ContactName 
    from 
     Contacts c 
    where 
     not exists (
      select 
       'x' 
      from 
       @list l 
      where 
       not exists (
        select 
         'x' 
        from 
         Submissions s 
        where 
         s.ContactID = c.ContactID and 
         s.SubmissionTypeID = l.SubmissionTypeID 
       ) 
     ) 
) 
select 
    c.ContactName, 
    t.SubmissionType 
from 
    c 
     inner join 
    Submissions s 
     on c.ContactId = s.ContactId 
     inner join 
    SubmissionTypes t 
     on s.SubmissionTypeID = t.SubmissionTypeID 
     inner join 
    @list l 
     on t.SubmissionTypeID = l.SubmissionTypeID; 

Example SQLFiddle

0
Try this.. It works fine to me 

DECLARE @list TABLE (SubmissionTypeID int not null primary key); 

INSERT INTO @list VALUES(1); -- values to search for. 

SELECT C.ContactName, ST.SubmissionTypeName 
FROM 
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY S.ContactID ORDER BY S.ContactID) AS RCount 
FROM 
Submission S 
WHERE EXISTS 
(SELECT 1 FROM @list l WHERE l.SubmissionTypeID = S.SubmissionTypeID)) AS Result 
INNER JOIN Submission S1 ON S1.ContactID = Result.ContactID 
INNER JOIN Contacts C ON C.ContactID = Result.ContactID 
INNER JOIN SubmissionTypes ST ON ST.SubmissionTypeID = S1.SubmissionTypeID 
WHERE RCOunt = (SELECT COUNT(DISTINCT SubmissionTypeID) FROM @list) 
AND EXISTS 
(SELECT 1 FROM @list l WHERE l.SubmissionTypeID = ST.SubmissionTypeID) 
;