SQL Query用于获取具有子记录列表的父表的记录

Ros*_*man 3 sql sql-server-2005 hierarchical-data

我在MS SQL Server 2005数据库(父和子)中有两个表,其中父表可能与许多子记录相关.[Child.parent_id]与[parent.id]相关.子表还有列[foo]我需要将父表中的所有记录带回来,其中[child.foo]匹配每个参数.例如,我希望所有父记录的[child.foo]值为'fizz',[child.foo]值为'buzz'.我已经尝试了以下查询,但它返回的记录只匹配一个.

SELECT     Parent.ID
FROM         Parent 
INNER JOIN Child ON Parent.ID = Child.parent_id
WHERE     (Child.foo = 'fizz')
UNION ALL
SELECT     Parent_1.ID
FROM         Parent AS Parent_1 
INNER JOIN Child AS Child_1 ON Parent_1.ID = Child_1.parent_id
WHERE     (Child_1.foo = 'buzz')
Run Code Online (Sandbox Code Playgroud)

mjv*_*mjv 7

这将返回所有父记录,其中[至少]一个孩子有'fizz'foo和[至少]一个孩子有'buzz'foo.这是我认为在问题中需要的内容.

此外,虽然是潜在的次优的,这个查询在某种意义上,它与大多数SQL实现,不仅更为现代的,其中CTE,子查询和相关结构的支持,支持的工作一般.

   SELECT DISTINCT Parent.ID
    FROM Parent
    JOIN Child C1 ON Parent.ID = C1.parent_Id
    JOIN Child C2 ON Parent.ID = C2.parent_id
    WHERE C1.foo = 'fizz'
      AND C2.foo = 'buzz'
Run Code Online (Sandbox Code Playgroud)

编辑:
现在Joel Potter在他的回答中修复了查询,我们可能同意他的方法比上面列出的查询有几个优点(请给他几个+代表).特别是:

  • 当我们添加或删除列foo的目标值时,查询的结构不会更改.
  • 查询可能更容易优化[由服务器本身]
  • 查询的结构允许它处理过滤器定义的变化.例如,我们可以查询所有有孩子的父母,例如说foo的5个可能值中的2个存在.

以下是Joel的查询,略有修改,以显示如何扩展超过2个foo值.

SELECT Parent.Id
FROM Parent
INNER JOIN Child on Parent.Id = child.parent_id
WHERE Child.foo IN ('fizz', 'buzz')  -- or say, ... IN ('fizz', 'buzz', 'bang', 'dong')
GROUP BY Parent.Id
HAVING COUNT(DISTINCT Child.foo) = 2  -- or 4 ...  
Run Code Online (Sandbox Code Playgroud)


Joe*_*oel 6

我相信你想要这样的东西.

Select 
    Parent.Id
From Parent
    inner join Child on Parent.Id = child.parent_id
Where 
    Child.foo = 'fizz' or Child.foo = 'buzz'
Group By
    Parent.Id
Having
    count(distinct Child.foo) > 1
Run Code Online (Sandbox Code Playgroud)

这是测试脚本:

Create Table #parent ( id int )
Create Table #child ( parent_id int, foo varchar(32) )

insert into #parent (id) values (1)
insert into #parent (id) values (2)
insert into #parent (id) values (3)

insert into #child (parent_id, foo) values (1, 'buzz')
insert into #child (parent_id, foo) values (2, 'buzz')
insert into #child (parent_id, foo) values (3, 'buzz')
insert into #child (parent_id, foo) values (1, 'fizz')


Select 
    #parent.Id
From #parent
    inner join #child on #parent.id = #child.parent_id
Where 
    #child.foo = 'fizz' or #child.foo = 'buzz'
Group By
    #parent.Id
Having
    count(distinct #child.foo) > 1        

drop table #parent
drop table #child
Run Code Online (Sandbox Code Playgroud)

仅返回Id 1.