2009-01-26 17 views
8

Digamos que tengo dos tablas, "Padre" y "Niño". Parent-to-Child es una relación many: many, implementada a través de una tabla estándar de referencias cruzadas.Seleccionar el registro primario con todos los niños en SQL

Quiero encontrar todos los registros de Parent a los que hacen referencia TODOS los miembros de un conjunto dado de Child utilizando SQL (en particular, T-SQL de MS SQL Server; la sintaxis de 2005 es aceptable).

Por ejemplo digamos que tengo:

  • elemento de la lista
  • Padres Alice
  • Padre Bob
  • Charlie Niño hace referencia a Alice, Bob
  • David Niño hace referencia a Alice
  • Eva Niño referencias Bob

Mis objetivos son:

  • si tengo hijos Charlie, quiero que el conjunto de resultados para incluir Alice y Bob
  • si tengo hijos Charlie y David, quiero que el conjunto de resultados para incluir Alice y NO Bob.
  • Si tengo hijos Charlie, David y Eva, quiero que el conjunto de resultados no incluya a nadie.
+0

¿Cómo es un FK estándar si el niño Charlie puede hacer referencia tanto a Alice como a Bob? –

+0

Está bien, Mark, las personas que necesitan ayuda para escribir consultas rara vez pueden formularlas correctamente. –

+0

Lo siento, no estaba claro: Padre: El niño es muchos: muchos. –

Respuesta

6

Basándose en un truco numérico (donde el número de enlaces entre padres e hijos = el número de niños, ese padre está vinculado a todos los niños):

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

Ese es el enfoque que conocía; Esperaba evitar el truco numérico. Pero tu respuesta vale la pena un voto positivo de todos modos. :-) –

2

Aquí es una respuesta.

SQL query: Simulating an "AND" over several rows instead of sub-querying

Y aquí es una aplicación específica de que a este problema.

SELECT * FROM Parents 
WHERE ParentId in 
(
    SELECT ParentId FROM ChildParent 
    WHERE ChildId in 
    (
    SELECT ChildId FROM Child 
    WHERE ChildName in ('Charlie', 'David') 
) 
    GROUP BY ParentId 
    HAVING COUNT(*) = 2 
) 
2

(supongo que donde dice "Eva Niño hace referencia a Eva" que quería decir "Eva Niño hace referencia a Bob", ¿verdad?)

Creo que ya lo tengo ... se ve mal ... el secreto es la doble negación ... es decir, todos para los que es verdad, es lo mismo que para nadie lo que es falso ... (vale, tengo problemas con mi inglés, pero supongo que entiendes lo que quiero decir)

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

así, espero que ayude ...

+0

Sí, envié la referencia de Eve-> Bob. Gracias por señalar eso. –

Cuestiones relacionadas