I'm trying to create a query to obtain zone data in preparation to moving the column to another table. How our DB is set up is that we have assets and cables. One asset can have many cables but a cable cannot have multiple assets. We're currently trying to move the Zone field from the Cable table (ex. Below) to the Asset table.
A_ID C_ID Zone
--------------------------
1 1 Green
1 2 Green
1 3 Yellow
2 4 Green
2 5 Red
3 6 Yellow
3 7 Yellow
3 8 Yellow
3 9 Red
The way I want it to be set up for the Asset table is if the Asset contains multiple cables with different zones, if one of the zones is Yellow it defaults to Yellow (ex. 3 green cables, 1 yellow cable - Asset_ID has Yellow zone). Next if it doesn't have any Yellows but has at least 1 red, it defaults to Red (ex. 2 green cables, 3 red cables - Asset_ID has Red Zone). Only if it just has Green zones then it defaults to Green.
Using the sample table above these are the results I would expect.
Expected Results
A_ID Zone
-------------
1 Yellow
2 Red
3 Yellow
I'm trying to use CASE statements but I'm having difficulty formulating the query to group the results correctly.
Any help would be greatly appreciated, thank you in advance.
No case or if statement needed. Think in sets. You need to assign a priority join to the priority and select the one with the highest priority first. Like this
WITH Priority AS
(
SELECT * FROM (
VALUES
('Yellow', 1),
('Red', 2),
('Green', 3)
) AS P(Zone,P)
)
SELECT A_ID, Zone
FROM (
SELECT A_ID, Zone
ROW_NUMBER() OVER (PARTITION BY A_ID ORDER BY P.P ASC) AS RN
FROM AssetTable A
LEFT JOIN Priority P ON A.Zone = P.Zone
) SUB
WHERE RN = 1
Not sure if my syntax is right for VALUES in CTE for Oracle. if that gives an error replace with this:
WITH Priority AS
(
SELECT 'Yellow' AS Zone, 1 AS P
UNION ALL
SELECT 'Red' AS Zone, 2 AS P
UNION ALL
SELECT 'Green' AS Zone, 3 AS P
)
One way to do it using conditional aggregation and a case
expression.
select a_id
,case when yellow_count >=1 then 'Yellow'
when yellow_count = 0 and red_count >=1 then 'Red'
when yellow_count = 0 and red_count = 0 and green_count >=1 then 'Green'
end zone
from (select a_id,
count(case when zone = 'Yellow' then 1 end) yellow_count,
count(case when zone = 'Red' then 1 end) red_count
count(case when zone = 'Green' then 1 end) green_count
from cable_table
group by a_id) t
Why just don't do a simple:
SELECT A_ID, MAX( Zone )
FROM table
GROUP BY A_ID
if some A_ID has Yellow
then max( Zone ) returns Yellow
if some A_ID hasn't Yellow
, but has Red
then max( Zone ) returns Red <br> otherwise (no
Yellow nor
Red ) max( Zone ) returns
Green`
and example:
with data as (
select 1 a_id, 1 c_id , 'Green' zone from dual union all
select 1 , 2 , 'Green' from dual union all
select 1 , 3, 'Yellow' from dual union all
select 2 , 4 , 'Green' from dual union all
select 2 , 5 , 'Red' from dual union all
select 3 , 6 , 'Yellow' from dual union all
select 3 , 7 , 'Yellow' from dual union all
select 3 , 8 , 'Yellow' from dual union all
select 3 , 9 , 'Red' from dual
)
select a_id, max( zone )
from data
group by a_id
A_ID MAX(ZO
---------- ------
1 Yellow
2 Red
3 Yellow
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.