SQL-Query: EXISTS in Subtable
Reasoning
LEFT OUTER JOIN
excludes all idData's that have an id different from 11 or 34HAVING
excludes all idData's that only have a 34- Remaining records (should) satisfy all constraints
Test data
DECLARE @tabData TABLE (idData INTEGER)
DECLARE @tabDataDetail TABLE (fiData INTEGER, fiActionCode INTEGER)
INSERT INTO @tabData VALUES (1)
INSERT INTO @tabData VALUES (2)
INSERT INTO @tabData VALUES (3)
INSERT INTO @tabData VALUES (4)
INSERT INTO @tabData VALUES (5)
/* Only idData 1 & 2 should be returned */
INSERT INTO @tabDataDetail VALUES (1, 11)
INSERT INTO @tabDataDetail VALUES (2, 11)
INSERT INTO @tabDataDetail VALUES (2, 34)
INSERT INTO @tabDataDetail VALUES (3, 99)
INSERT INTO @tabDataDetail VALUES (4, 11)
INSERT INTO @tabDataDetail VALUES (4, 99)
INSERT INTO @tabDataDetail VALUES (5, 34)
Query
SELECT *
FROM @tabData d
INNER JOIN @tabDataDetail dd ON dd.fiData = d.idData
INNER JOIN (
SELECT idData
FROM @tabData d
INNER JOIN @tabDataDetail dd ON dd.fiData = d.idData
LEFT OUTER JOIN (
SELECT fiData
FROM @tabDataDetail
WHERE fiActionCode NOT IN (11, 34)
) exclude ON exclude.fiData = d.idData
WHERE exclude.fiData IS NULL
GROUP BY
idData
HAVING MIN(fiActionCode) = 11
) include ON include.idData = d.idData
Select ...
From tabData As T1
Where Exists (
Select 1
From tabDataDetail As TDD1
Where TDD1.fiData = T1.idData
And TDD1.fiactionCode = 11
)
And Not Exists (
Select 1
From tabDataDetail As TDD1
Where TDD1.fiData = T1.idData
And TDD1.fiactionCode Not In(11,34)
)
To expand on my logic, the first check (a correction) is to ensure that a row with fiActionCode = 11 exists. The second check works by first defining the set of rows we do not want. We do not want anything that is something other than fiActionCode = 11 or 34. Because that is the set of items we do not want, we search for anything that does not exist in that set.
Edit : Apols - I see what you mean with child rows. This isn't particular efficient. Thanks also to Lieven for the data.
SELECT idData FROM
tabData td
WHERE EXISTS
(
SELECT 1
FROM tabDataDetail tdd
WHERE tdd.fiData = td.idData AND fiActionCode = 11
)
AND NOT EXISTS
(
SELECT 1
FROM tabDataDetail tdd
WHERE tdd.fiData = td.idData AND fiActionCode <> 11
)
UNION
SELECT idData
FROM tabData td
WHERE EXISTS
(
SELECT 1
FROM tabDataDetail tdd
WHERE tdd.fiData = td.idData AND fiActionCode = 11
)
AND EXISTS
(
SELECT 1
FROM tabDataDetail tdd
WHERE tdd.fiData = td.idData AND fiActionCode = 34
)
AND NOT EXISTS
(
SELECT 1
FROM tabDataDetail tdd
WHERE tdd.fiData = td.idData AND fiActionCode NOT IN (11, 34)
)
Edited my answer based on clarification given in comments on other answers.
select td.idData
from tabData td
left join tabDataDetail tdd
on td.idData = tdd.fiData
and tdd.fiActionCode = 11
left join tabDataDetail tdd2
on td.idData = tdd2.fiData
and tdd2.fiActionCode = 34
left join tabDataDetail tdd3
on td.idData = tdd3.fiData
and tdd3.fiActionCode not in (11,34)
where (tdd.fiData is not null
or (tdd.fiData is not null and tdd2.fiData is not null))
and tdd3.fiData is null
group by td.idData