Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查询以获取具有子记录列表的父表的记录_Sql_Sql Server 2005_Hierarchical Data - Fatal编程技术网

SQL查询以获取具有子记录列表的父表的记录

SQL查询以获取具有子记录列表的父表的记录,sql,sql-server-2005,hierarchical-data,Sql,Sql Server 2005,Hierarchical Data,我在MS SQL Server 2005数据库中有两个表,即父表和子表,其中父表可能与许多子记录相关。[Child.parent\u id]与[parent.id]相关。子表也有列[foo],我需要返回父表中[child.foo]与一对多参数中的每个参数匹配的所有记录。例如,我希望所有父记录的[child.foo]值为'fizz',[child.foo]值为'buzz' 我尝试了下面的查询,但它返回的记录只与一个匹配 SELECT Parent.ID FROM Paren

我在MS SQL Server 2005数据库中有两个表,即父表和子表,其中父表可能与许多子记录相关。[Child.parent\u 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')

我相信你想要这样的东西

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
以下是测试脚本:

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

仅返回Id 1。

这将得到您想要的结果:

SELECT p.ID
FROM Parent p
WHERE EXISTS
(
    SELECT 1 FROM Child c WHERE c.parent_id = p.ID AND c.foo IN ('fizz','buzz')
)

这将返回所有父记录,其中[至少]有一个子项具有“fizz”foo,[至少]有一个子项具有“buzz”foo。我认为这是问题所需要的

此外,虽然该查询可能是次优的,但从某种意义上讲,它是通用的,可以用于大多数SQL实现,而不仅仅是支持CTE、子查询和相关构造的更现代的SQL实现

   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'
编辑
既然Joel Potter在他的回答中修正了这个问题,我们可能同意他的方法比上面列出的问题有几个优点(请给他几次+重复)。特别是:

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

我想和大家分享一下Joel的优秀答案的简单概括。这里的想法是能够将包含“目标”子级的任意表作为表值参数或拆分分隔字符串传递到过程中。虽然这很好,但是如果有一个类似的查询,使用LIKE而不是IN进行匹配也很好

--Parents whose children contain a subset of children

--setup
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 (1, 'buzz')
insert into #child (parent_id, foo) values (1, 'fizz')
insert into #child (parent_id, foo) values (2, 'buzz')
insert into #child (parent_id, foo) values (2, 'fizz')
insert into #child (parent_id, foo) values (2, 'bang')
insert into #child (parent_id, foo) values (3, 'buzz')

--create in calling procedure
declare @tblTargets table (strTarget varchar(10))
insert into @tblTargets (strTarget) values ('fizz')
insert into @tblTargets (strTarget) values ('buzz')

--select query to be called in procedure; 
--  pass @tblTargets in as TVP, or create from delimited string via splitter function
select #parent.id       --returns 1 and 2
    from #parent
       inner join #child on #parent.id = #child.parent_id
    where #child.foo in (select strTarget from @tblTargets)
    group by #parent.id
    having count(distinct #child.foo) = (select COUNT(*) from @tblTargets)        

--cleanup
drop table #parent
drop table #child

我已经指定了数据库。我只是假设解决方案与数据库无关,但我不需要。递归CTE是ANSI标准,但实现滞后-只有3个dbs支持
:Oracle、SQL Server和DB2。虽然问题是模棱两可的,但我认为OP希望家长既有“嘶嘶”的
,又有“嗡嗡”的孩子。上面的查询将返回具有“fizz”或“buzz”孩子的父母。啊,你可能是对的。因此,我将投票表决你的答案。例如,如果给定的家长有两个(或更多)foo值为'fizz'@mjv:你是对的,那么这个查询将失败。将
count(*)
替换为
count(distinct Child.foo)
以更正该错误。马上开始。我编辑了我的答案,以指向您现在已修复的解决方案,因为我发现它更通用,更[自动]优化。然而,这种类型查询的查询计划在很大程度上取决于特定的SQL实现和数据的特定统计配置文件。@mjv:我不确定分组与联接的性能。如果你有基准,那将是伟大的看到。不过,关于特定的RDBMS是一个因素,您可能是对的。