Home > database >  Oracle sql - Case
Oracle sql - Case

Time:10-25

I have table like this:

ID PRODUCT
1 APPLE
2 SUMSUNG
2 APPLE
3 HUAWEI
4 XIAMO
4 APPLE

The product is devided into two types: ios and android. I want to get a table like this:

ID IOS ANDDROID
1 YES NO
2 YES YES
3 NO YES
4 YES YES

I tried :

select id,  
       case when product = 'APPLE' THEN 'YES' ELSE 'NO' END as 'IOS',
       case when product in ('SUMSUNG', 'HUAWEI', 'XIAMO') THEN 'YES' ELSE 'NO' END AS 'ANDROID'
from table

But i got this table:

ID IOS ANDDROID
1 YES NO
2 YES NO
2 NO YES
3 NO YES
4 YES NO
4 NO YES

CodePudding user response:

You'll need yet another - mapping - table which shows which operating system belongs to which product. Yes, you can hardcode it into the query, but that's generally a bad idea. You can't modify query every time new product appears on the market, can you? Sure you can, but you shouldn't.

SQL> with mapping (product, os) as
  2    (select 'APPLE'  , 'IOS'     from dual union all
  3     select 'SAMSUNG', 'ANDROID' from dual union all
  4     select 'HUAWEI' , 'ANDROID' from dual union all
  5     select 'XIAMO'  , 'ANDROID' from dual
  6    ),
  7  your_table (id, product) as
  8    (select 1, 'APPLE'   from dual union all
  9     select 2, 'SAMSUNG' from dual union all
 10     select 2, 'APPLE'   from dual union all
 11     select 3, 'HUAWEI'  from dual union all
 12     select 4, 'XIAMO'   from dual union all
 13     select 4, 'APPLE'   from dual
 14    )
 15  select y.id,
 16    max(case when p.os = 'IOS' then 'YES' else 'NO' end) as ios,
 17    max(case when p.os = 'ANDROID' then 'YES' else 'NO' end) as android
 18  from your_table y join mapping p on p.product = y.product
 19  group by y.id
 20  order by y.id;

        ID IOS AND
---------- --- ---
         1 YES NO
         2 YES YES
         3 NO  YES
         4 YES YES

SQL>

CodePudding user response:

You can aggregate to ensure that the id only shows up once:

select id,  
       MAX(case when product = 'APPLE' THEN 'YES' END) as 'IOS',
       MAX(case when product in ('SUMSUNG', 'HUAWEI', 'XIAMO') THEN 'YES' END) AS 'ANDROID'
from table
GROUP BY id

That ensures you get one row per id - but you get NULL instead of 'NO'. To fix that use COALESCE.

select id,  
       COALESCE(MAX(case when product = 'APPLE' THEN 'YES' END),'NO') as 'IOS',
       COALESCE(MAX(case when product in ('SUMSUNG', 'HUAWEI', 'XIAMO') THEN 'YES' END),'NO') AS 'ANDROID'
from table
GROUP BY id
  • Related