[英]SQL Query to get records from a child table which does not have a parent in the parent table?
[英]SQL Query to get records of parent table that have a list of child records
我在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')
這將返回所有父記錄,其中[至少]一個孩子有'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在他的回答中修復了查詢,我們可能同意他的方法比上面列出的查詢有幾個優點(請給他幾個+代表)。 尤其是:
以下是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 ...
我相信你想要這樣的東西。
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')
)
我想分享這個簡單概括的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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.