I'm trying to select the rows for MEDs (type) and the related child rows for ORAL (type) where each MED type has multiple ORAL types from the following table.
ID | PARENT_ID | TYPE |
---|---|---|
1 | NULL | MED |
2 | 1 | ORAL |
3 | NULL | MED |
4 | 3 | ORAL |
5 | 3 | IV |
6 | NULL | MED |
7 | 6 | ORAL |
8 | NULL | MED |
9 | 8 | ORAL |
12 | NULL | MED |
13 | 12 | ORAL |
14 | 12 | IV |
15 | 12 | ORAL |
This should return rows with ID 12, 13, and 15. I've tried the following using a CTE to my multiple counts of ORAL rows. Then tried joining that to pull the three rows I need, but it doesn't return the way I think it should. It's returning the IDs but only in two rows.
WITH COUNT_CTE (ID, CNT)
AS
(
SELECT A.ID, COUNT(A.ID) AS CNT
FROM Table1 A
JOIN Table1 B
ON A.ID = B.PARENT_ID
WHERE A.TYPE = 'MED' and B.TYPE = 'ORAL'
GROUP BY A.ID
)
SELECT A.*, B.*
FROM Table1 A
JOIN Table1 B
ON A.ID = B.ID
JOIN COUNT_CTE C
ON A.ID = C.ID
WHERE A.TYPE = 'MED' AND B.TYPE = 'ORAL' AND C.CNT > 1
This returned:
ID | PARENT_ID | TYPE | ID | PARENT_ID | TYPE |
---|---|---|---|---|---|
12 | NULL | MED | 13 | 12 | ORAL |
12 | NULL | MED | 15 | 12 | ORAL |
I'm not sure if a CTE is even needed or if the group by could be done inside a subquery. Either way I'm not sure how to separate the children into their own rows to look like the below correct return.
The return should be:
ID | PARENT_ID | TYPE |
---|---|---|
12 | NULL | MED |
13 | 12 | ORAL |
15 | 12 | ORAL |
CodePudding user response:
You can do this in three steps. Count the children, like you are. Then join on only rows with multiple children and child or parent rows.
-- Get a count of how many ORAL rows each MED parent has.
with child_count as (
SELECT A.id, COUNT(A.ID) AS CNT
FROM Table1 A
JOIN Table1 B
ON A.ID = B.PARENT_ID
WHERE A.TYPE = 'MED' and B.TYPE = 'ORAL'
GROUP BY A.ID
)
select table1.*
from child_count cc
join table1
-- Filter for only rows with a parent with more than one child.
on cc.cnt > 1
-- And only child ORAL rows, or parent rows.
and (
(cc.id = table1.parent_id and table1.type = 'ORAL')
or cc.id = table1.id
)
CodePudding user response:
Many solutions, here's one using using INTERSECT within a CTE.
with target_meds as (
select id
from my_table
where type = 'MED'
intersect
select parent_id
from my_table
where type = 'ORAL'
group by 1
having count(id) > 1
)
select m.*
from my_table m
join target_meds t
on coalesce(m.parent_id, m.id) = t.id
where m.type in ('MED', 'ORAL');
id | parent_id | type |
---|---|---|
12 | null | MED |
13 | 12 | ORAL |
15 | 12 | ORAL |