2009-01-26 9 views
8

Disons que j'ai deux tables, "Parent" et "Enfant". Parent-to-Child est une relation many: many, implémentée via un tableau de références croisées standard.Sélectionnez l'enregistrement parent avec tous les enfants dans SQL

Je veux trouver tous les enregistrements de Parent qui sont référencés par TOUS les membres d'un ensemble donné d'enfants utilisant SQL (en particulier la syntaxe T-SQL de MS SQL Server, 2005 est acceptable).

Par exemple, disons que j'ai:

  • Liste item
  • Parent Alice
  • Parent Bob
  • enfant Charlie référence Alice, Bob
  • enfant David fait référence à Alice
  • Eve enfant références Bob

Mes objectifs sont les suivants:

  • Si j'ai des enfants Charlie, je veux le jeu de résultats à inclure Alice et Bob
  • Si j'ai des enfants Charlie et David, je veux le jeu de résultats à inclure Alice et PAS Bob.
  • Si j'ai des enfants Charlie, David et Eve, je veux que le jeu de résultats n'inclue personne.
+0

Comment est-ce un FK standard si l'enfant Charlie peut faire référence à Alice et Bob? –

+0

C'est bon Mark, les gens qui ont besoin d'aide pour rédiger des requêtes peuvent rarement poser correctement. –

+0

Désolé, n'était pas clair: Parent: Enfant est beaucoup: beaucoup. –

Répondre

6

En se fondant sur un tour numérique (où le nombre de liens parent-enfant = le nombre d'enfants, ce parent est lié à tous les enfants):

SELECT Parent.ParentID, COUNT(*) 
FROM Parent 
INNER JOIN ChildParent 
    ON ChildParent.ParentID = Parent.ParentID 
INNER JOIN Child 
    ON ChildParent.ChildID = Child.ChildID 
WHERE <ChildFilterCriteria> 
GROUP BY Parent.ParentID 
HAVING COUNT(*) = (
    SELECT COUNT(Child.ChildID) 
    FROM Child WHERE <ChildFilterCriteria> 
) 
+0

C'est l'approche que je connaissais; J'espérais éviter le tour numérique. Mais votre réponse vaut la peine d'être votée de toute façon. :-) –

2

(je suppose que vous avez dit "fait référence à Eve Child Eve" que vous vouliez dire "fait référence à Eve Bob Child", non?)

Je pense que je l'ai ... semble laid ... le secret est la double négation ... c'est-à-dire, tout le monde pour qui c'est vrai, c'est la même chose que n'importe qui pour qui est faux ... (ok, j'ai des ennuis avec mon anglais, mais je suppose que tu comprends)

 
select * from parent 

parent_id        name 
--------------------------------------- -------------------------------------------------- 
1          alice 
2          bob 

select * from child 

child_id        name 
--------------------------------------- -------------------------------------------------- 
1          charlie 
2          david 
3          eve 

select * from parent_child 

parent_id        child_id 
--------------------------------------- --------------------------------------- 
1          1 
2          1 
1          2 
2          3 

select * from parent p 
where not exists(
    select * from child c 
    where 
     c.child_id in (1, 2, 3) and 
     not exists(
      select * from parent_child pc where 
       pc.child_id = c.child_id and 
       pc.parent_id = p.parent_id 
     ) 
) 

--when child list = (1) 
parent_id        name 
--------------------------------------- -------------------------------------------------- 
1          alice 
2          bob 

--when child list = (1, 2) 
parent_id        name 
--------------------------------------- -------------------------------------------------- 
1          alice 

--when child list = (1, 2, 3) 
parent_id        name 
--------------------------------------- -------------------------------------------------- 

bien

, j'espère que cela aide ...

+0

Oui, j'ai utilisé la référence Eve-> Bob. Merci d'avoir fait remarquer cela. –

Questions connexes