在SQL中选择包含所有子项的父记录

时间:2009-01-26 18:02:37

标签: sql sql-server sql-server-2005 tsql

假设我有两个表,“父母”和“孩子”。 Parent-to-Child是一个很多:很多关系,通过标准的交叉引用表实现。

我想查找使用SQL的给定Child组的所有成员引用的Parent的所有记录(特别是MS SQL Server的T-SQL;可以接受2005语法)。

例如,假设我有:

  • 列表项
  • Parent Alice
  • Parent Bob
  • Child Charlie引用Alice,Bob
  • Child David引用Alice
  • 儿童夏娃参考鲍勃

我的目标是:

  • 如果我有Child Charlie,我希望结果集包含Alice和Bob
  • 如果我有Child Charlie和David,我希望结果集包含Alice和 NOT Bob。
  • 如果我有Child Charlie,David和Eve,我希望结果集中包含nobody。

3 个答案:

答案 0 :(得分:6)

依靠数字技巧(父子链接的数量=孩子的数量,父母与所有孩子的链接):

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

答案 1 :(得分:2)

这是一个答案。

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

这是这个问题的具体应用。

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 :(得分:2)

(我猜你在哪里说“儿童夏娃参考夏娃”你的意思是“儿童夏娃参考鲍勃”,对吧?)

我想我已经拥有它......看起来很丑陋......秘诀就是双重否定......也就是说,每个人都是真实的,就像任何人都是假的一样...... (好吧,我的英语很麻烦,但我猜你明白我的意思)

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

好吧,我希望它有所帮助...