【问题标题】:Waterfall Case Statement瀑布案例声明
【发布时间】:2019-01-16 16:22:14
【问题描述】:

我正在尝试编写一个 case 语句,一旦从每个“WHEN”语句中找到正确的值,它就会返回一个值。一旦找到符合条件的值,查询就不应尝试评估其他语句。

SELECT
    DT1.COMPANY_ID
    , CASE
    WHEN DT1.RATING_NUMBER = 2 THEN DT1.UNIQUE_ENTRY_ID
    WHEN DT1.RATING_NUMBER = 1 THEN DT1.UNIQUE_ENTRY_ID
    WHEN DT1.RATING_NUMBER = 3 THEN DT1.UNIQUE_ENTRY_ID
     END AS UNIQUE_ENTRY_ID
FROM
    RATINGS_DATA DT1

样本数据

create table COMP_RESULTS (COMPANY_ID varchar2(20),RATING_NUMBER number, UNIQUE_ENTRY_ID varchar2(20));

insert into COMP_RESULTS values ('Org00001','1','ENTRY_C1_1');
insert into COMP_RESULTS values ('Org00001','2','ENTRY_C1_2');
insert into COMP_RESULTS values ('Org00001','3','ENTRY_C1_3');
insert into COMP_RESULTS values ('Org00002','2','ENTRY_C2_2');
insert into COMP_RESULTS values ('Org00002','3','ENTRY_C2_3');
insert into COMP_RESULTS values ('Org00003','3','ENTRY_C3_3');

每天都会发布每家公司的评级数字;有时是全部,有时不是全部)。如果评级编号为 1,则生成相应的唯一 ID。如果评级数为 2,则发布相应的 ID。如果评级 '1' 被释放,查询会带来公司 ID 和相应的UNIQUE_ENTRY_ID。它不应该费心查看第二个“WHEN”语句。如果评级编号“1”不存在,则尝试 2,如果都不存在,则尝试 3,依此类推。

样本结果

Org00001    2   ENTRY_C1_1
Org00002    2   ENTRY_C2_2
Org00003    3   ENTRY_C3_3

有人可以帮忙吗?

【问题讨论】:

  • 请发布一些示例数据和预期结果
  • 也许我误解了这个问题,但这不是 SQL CASE 语句的工作方式吗?您是否尝试做一些与平常不同的事情?
  • 请注意,CASE WHEN 就是这样工作的。一旦 WHEN 标准有效,它就会脱离它,忽略它之后的 WHEN。
  • 您是否为每个公司返回多行,但您只希望每个公司首先匹配的行中的值? “每一天”在哪里适合 - 什么日子?一家公司可以有多行相同的评级编号,如果可以,您将如何决定使用哪个关联的条目 ID? 在您的问题中添加示例数据和预期结果(使用 edit,而不是 cmets)。
  • @JoshuaTinashe - 它 case 表达式的工作原理。你问错了问题……你的问题不在于 case 表达式如何工作,而在于你试图用一个来解决它不适合的问题。

标签: sql oracle if-statement case


【解决方案1】:

case 表达式会在找到匹配项后立即停止计算项。所以我认为你问错了问题。看起来你根本不想要一个 case 表达式。

根据您的示例数据和结果,您似乎想要使用 first 进行聚合,类似于:

select dt1.company_id,
  max(dt1.unique_entry_id)
    keep (dense_rank first order by dt1.rating_number) as unique_entry_id
from comp_results dt1
group by dt1.company_id;

COMPANY_ID           UNIQUE_ENTRY_ID     
-------------------- --------------------
Org00001             ENTRY_C1_1          
Org00002             ENTRY_C2_2          
Org00003             ENTRY_C3_3          

这仍会评估每一行,但随后会聚合并仅保留具有最低 rating_number 的行 - 这与您想要的优先顺序相匹配。

db<>fiddle

编辑后,如果评级数字不是数字顺序,您可以将 case 表达式添加回 order by 子句以指定所需的顺序:

select dt1.company_id,
  max(dt1.unique_entry_id) keep (dense_rank first
    order by case dt1.rating_number
             when 2 then 1
             when 1 then 2
             when 3 then 3
      end) as unique_entry_id
from comp_results dt1
group by dt1.company_id;

Updated db<>fiddle

【讨论】:

  • 如果按特定顺序应用评级 ID,这将起作用。不幸的是,事实并非如此
  • @JoshuaTinashe - 怎么会这样?在你的问题中,你说评级是按这个顺序排列的,这就是你要求的结果。
  • 我现在真的明白了——我需要先根据标准对数据进行排名!谢谢,你是对的,我问错问题了!
  • 我可能仍然误解了这个问题。这不会仅过滤 RATING_NUMBER OP 正在寻找的结果。为RATING_NUMBER添加另一条记录是42,它将在此查询的结果中被提取。
  • @Shawn - 如果您为这三个公司 ID 之一添加 42,则不会显示; case 表达式的计算结果为 null,默认情况下最后排序。如果您的客户只有 42 个,那么它会显示出来,是的。目前尚不清楚是否可以有任何其他值,和/或是否应该只过滤这三个值(我不认为它需要过滤,但没有指定任何一种方式),但这很容易添加如果需要的话。还不清楚客户是否可以有超过一行的评级,或者如果可以的话如何处理 - 希望还有另一列可以添加到 order-by...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 2023-03-02
相关资源
最近更新 更多