Выберите родительскую запись со всеми дочерними элементами в SQL - PullRequest
8 голосов
/ 26 января 2009

Допустим, у меня есть две таблицы: «Родитель» и «Ребенок». Родитель-ребенок - это отношение «многие: многие», реализованное через стандартную таблицу перекрестных ссылок.

Я хочу найти все записи Parent, на которые ссылаются ВСЕ члены данного набора Child с использованием SQL (в частности, T-SQL MS SQL Server; синтаксис 2005 приемлем).

Например, скажем, у меня есть:

  • Элемент списка
  • Родитель Алиса
  • Родитель Боб
  • Ребенок Чарли ссылается на Алису, Боба
  • Ребенок Дэвид ссылается на Алису
  • Чайлд Ева ссылается на Боба

Мои цели:

  • Если у меня есть Дети Чарли, я хочу, чтобы набор результатов включал Алису и Боба
  • Если у меня есть Дети Чарли и Дэвид, я хочу, чтобы в набор результатов были включены Алиса и НЕ Боб.
  • Если у меня есть Дети, Чарли, Дэвид и Ева, я хочу, чтобы набор результатов не включал никого.

Ответы [ 3 ]

6 голосов
/ 26 января 2009

Опираясь на числовую уловку (где число связей родитель-потомок = количество детей, этот родительский элемент связан со всеми дочерними элементами):

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>
)
2 голосов
/ 26 января 2009

(Полагаю, где вы сказали "Детская Ева ссылается на Еву", вы имели в виду "Детская Ева ссылается на Боба", верно?)

Я думаю, что у меня это есть ... выглядит некрасиво ... секрет в двойном отрицании ... то есть, каждый, для которого это правда, такой же, как никто другой, для которого это ложь ... (хорошо, у меня проблемы с моим английским, но я думаю, вы понимаете, о чем я)

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

ну, надеюсь, это поможет ...

2 голосов
/ 26 января 2009

Вот ответ.

SQL-запрос: моделирование «И» в нескольких строках вместо подзапроса

И вот конкретное применение этого к этой проблеме.

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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...