Reputation: 4367
I'm simplifying the problem, but the concept here should be the same...
Let's say we have a table FOO
with fields ID
and ATTRIB
, and a table BAR
with fields ID
, A_MATCHING_ID
, STATUS
. These tables look like this:
Table FOO:
ID - ATTRIB
=====
1001 - ATR_A
1002 - ATR_B
1003 - ATR_A
1004 - ATR_B
1005 - ATR_B
etc.
Table BAR:
ID - FOO_MATCHING_ID - STATUS
=====
9901 - 1001 - STAT_A
9902 - 1001 - STAT_A
9903 - 1001 - STAT_B
9904 - 1002 - STAT_C
9905 - 1002 - STAT_B
9906 - 1002 - STAT_B
9907 - 1003 - STAT_A
etc.
There is a one-to-many relationship of FOO
to BAR
.
I want to run a query on these two tables with a calculated/dependent field [HAS_STAT_A]:
Expected Query Result:
FOO_ID - HAS_STAT_A
=====
1001 - TRUE
1002 - FALSE
1003 - TRUE
How can I accomplish this?
SELECT FOO.ID AS FOO_ID, [FILL THIS IN] AS HAS_STAT_A
FROM FOO
JOIN BAR ON FOO.ID = BAR.FOO_MATCHING_ID;
I thought of using CASE
, but don't know how to use that across multiple records. I also thought of adding in some extra sub-queries, but wasn't sure how to arrange those, either.
This is similar, but not quite what I want to achieve. It led to me to something like the below, but I get GROUP BY
errors. When I add GROUP BY
, I get MISSING KEYWORD
errors.
SELECT FOO.ID AS FOO_ID,
INSTR (LISTAGG (BAR.STATUS, ',') WITHIN GROUP (ORDER BY BAR.STATUS), 'STAT_A') AS HAS_STAT_A
FROM FOO
JOIN BAR ON FOO.ID = BAR.FOO_MATCHING_ID;
Upvotes: 0
Views: 295
Reputation: 4825
If it is possible for there to be rows in foo
that have no matching rows in bar
, you might try something like this:
SELECT
foo.id AS foo_id,
NVL
(
(
SELECT
'TRUE'
FROM
bar
WHERE
bar.foo_matching_id = foo.id
AND
bar.STATUS = 'STAT_A'
AND
ROWNUM <= 1
),
'FALSE'
)
FROM
foo
There may be more efficient ways to rewrite this query.
Upvotes: 0
Reputation: 49
Here's one way to do it
SELECT
FOO.ID AS FOO_ID,
SUM(CASE WHEN BAR.[STATUS]='STAT_A' THEN 1 ELSE 0 END) AS HAS_STAT_A
FROM FOO
INNER JOIN BAR ON FOO.ID = BAR.FOO_MATCHING_ID
GROUP BY
FOO.ID
You can also take this and filter out the rows where has_stat_a is 0 by using the "having" keyword
SELECT
FOO.ID AS FOO_ID,
SUM(CASE WHEN BAR.[STATUS]='STAT_A' THEN 1 ELSE 0 END) AS HAS_STAT_A
FROM FOO
INNER JOIN BAR ON FOO.ID = BAR.FOO_MATCHING_ID
GROUP BY
FOO.ID
HAVING
SUM(CASE WHEN BAR.[STATUS]='STAT_A' THEN 1 ELSE 0 END) = 1
Upvotes: 0
Reputation: 238088
select foo.id as foo_id
, case
when max(case when lower(trim(bar.status)) = 'stat_a' then 1 end) = 1 then 'true'
else 'false'
end as has_stat_a
from foo
join bar
on foo.id = bar.foo_matching_id
group by
foo.id
Upvotes: 4