Oracle中的CASE语句 - 取决于2列(不是1)多个

时间:2016-01-16 11:39:48

标签: oracle case multiple-columns

我有这样一张桌子 TABLE_ITEM_DEFINITION

╔═════════════════════╦══════════╦═══════════╗
║        Name         ║ Language ║ object_id ║
╠═════════════════════╬══════════╬═══════════╣
║ My Name in english  ║ en       ║ 123459098 ║
║ mon nom en espagnol ║ sp       ║ 123459098 ║
║ my name in Klingon  ║ kl       ║ 123459098 ║
╚═════════════════════╩══════════╩═══════════╝

在我的查询后显示对象时:我打算获取英文名称(如果存在),否则如果存在则为西班牙语,否则为klingon..I.E。我只会显示一个首先符合我标准的名称。

4 个答案:

答案 0 :(得分:1)

您可以使用COALESCE并自行加入:

SELECT m.*, COALESCE(t1.Name, t2.Name, t3.Name) AS result
FROM MAIN_OBJECT_TABLE m
LEFT JOIN TABLE_ITEM_DEFINITION t1
  ON m.object_id = t1.object_id
  AND t1.Language = 'en'
LEFT JOIN TABLE_ITEM_DEFINITION t2
  ON m.object_id = t2.object_id
  AND t2.Language = 'sp'
LEFT JOIN TABLE_ITEM_DEFINITION t3
  ON m.object_id = t3.object_id
  AND t3.Language = 'kl'
WHERE m.object_id = 123459098;

LiveDemo

答案 1 :(得分:1)

我认为在这种情况下,最好的方法是先改进你的设计。由于您有许多具有不同语言名称的对象,因此您应该为语言优先级创建一个表:

create table language_priority (
language_name  varchar2(2),
priority_level number);

insert into language_priority(language_name, priority_level) values ('en', 1);
insert into language_priority(language_name, priority_level) values ('sp', 2);
insert into language_priority(language_name, priority_level) values ('kl', 3);

现在您使用TABLE_ITEM_DEFINITION加入此表并选择具有最高优先级的行:

select name 
  from (select name, row_number() over (order by lp.priority_level) rn
          from TABLE_ITEM_DEFINITION tid,
               language_priority lp
         where lp.language_name = tid.language
           and tid.object_id = 123459098)
 where rn = 1

您还可以制作"优先级表"没有创建表,使用with子句,但这个解决方案是一种硬编码:

with language_priority as (
        select 'en' language_name, 1 priority_level union all
        select 'sp' language_name, 2 priority_level union all
        select 'kl' language_name, 3 priority_level)
select name 
  from (select name, row_number() over (order by lp.priority_level) rn
          from TABLE_ITEM_DEFINITION tid,
               language_priority lp
         where lp.language_name = tid.language
           and tid.object_id = 123459098)
 where rn = 1

这两种解决方案都可以轻松添加许多新语言并改变其优先级。

答案 2 :(得分:0)

select name, object_id, language
from (
  select name, object_id, language, 
         row_number() over (order by decode(language, 'en', 1, 'sp', 2, 3) as rn
  from table_item_definition
  where object_id = 123459098 
) t
where rn = 1;

如果您需要将其加入main_object_table表,您可以这样做:

select m.*, 
       ti.name, 
       ti.language
from main_object_table  m
  join (
    select name, object_id, language, 
           row_number() over (partition by object_id order by decode(language, 'en', 1, 'sp', 2, 3) as rn
    from table_item_definition
  ) ti on ti.object_id = m.object_id and ti.rn = 1
where m.object_id = 123459098;

如果table_item_definition中根本没有行,那么您需要使用外部联接(left join)而不是内部联接。

答案 3 :(得分:0)

作为替代方案:

select UNIQUE object_id, 
       FIRST_VALUE(Name) OVER (PARTITION BY object_id 
                      ORDER BY  (case when Language = 'en' then 1
                      when Language = 'sp' then 2
                       else 3 end))
       from TABLE_ITEM_DEFINITION