2014-08-29 4 views
-1

J'ai besoin d'aide avec une requête SQL sur laquelle je travaille. Voici une version simplifiée des données avec lesquelles je travaille. J'ai 3 tables:Requête serveur SQL complexe

les contacts:

- ContactID 
- ContactName 

soumissions:

- SubmissionID 
- ContactID 
- SubmissionTypeID 

SubmissionTypes:

- SubmissionTypeID 
- SubmissionType 

J'ai besoin de retourner tous les contacts (joints à Submissions sur ContactID) où il y a des SubmissionTypeIDs qui correspondent à une liste de SubmissionTypeIDs. La partie difficile est que je veux seulement des résultats où un contact a un enregistrement de soumission avec un SubmissionTypeID qui correspond à chacune des valeurs dans la liste. Ainsi, par exemple, si j'avais ces données:

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 

Si mes SubmissionTypeID valeurs sont 1 et 2, je veux obtenir les résultats suivants:

Jim Johnson | Contact Form 
Jim Johnson | Request Form 

Je ne voudrais pas voir Sally Anderson parce qu'elle n'a pas d'enregistrement dans les soumissions pour les deux valeurs.

Je suppose qu'il y a plusieurs façons de le faire. Je suis ravi de voir vos idées.

Merci!

Répondre

1

Une façon est avec 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

Vous pouvez également COUNT où égal à 2 (vous avez 2 valeurs que vous vérifiez pour):

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) 

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

+0

en fonction d'autres contraintes, 'avoir count (*) = 2' pourrait devoir être' nombre ayant (submissiontypeid distinct) = 2'. +1 pour "intersect", cependant. – Laurence

+0

@Laurence convenu, normalement je ferais sans distinctif par défaut, mais je viens de l'éditer car il ya probablement une chance décente qu'un contact puisse avoir plus d'une soumission du même type. –

1

Voici une manière compliquée d'utiliser la double négation.

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