DB2 Case Statement - 如果最大值相同,则选择最小值

Posted

技术标签:

【中文标题】DB2 Case Statement - 如果最大值相同,则选择最小值【英文标题】:DB2 Case Statement - select lowest value if same maximum value 【发布时间】:2014-11-07 19:11:04 【问题描述】:

我正在尝试在 db2 中编写带有 case 语句的 sql,用于以下场景。根据特定的 ID,我们必须找到最大金额并标记最大金额的 ID。但是如果有两个相同的最大值,那么我们需要考虑最低的排名(按照 1、2、3、4、5 的顺序,然后是 0)。

所以在下面的例子中,max_amt_ind 应该是 Y 只用于 Rank 2 和 N 用于 rank 0 和 1。

ID      RANK    AMT     MAX_AMT_IND
13786   0       6.11    N
13786   1       2.9     N
13786   2       6.11    Y

以下查询将 Rank 0 和 Rank 2 标记为“Y”。我也尝试使用嵌套 case 语句,但找不到解决方案。任何帮助将不胜感激。

select a. id, a.rank,a. amt,b.max_amount,
case when a.amt=b.max_amount then 'Y'
            else 'N'
            end as max_amt_ind
from Table_1 a inner join 
( 
select id, max(amt) as max_amount from Table_1
where max_payer_ind is null and id=13786
group by id
) b on a. id=b. id 

提前感谢您!

【问题讨论】:

【参考方案1】:

您可以使用row_number()

select id, rank, amt,
       (case when row_number() over (partition by id
                                     order by amt desc,
                                              (case when rank = 0 then 1 else 0 end, rank desc)
                                    ) = 1
             then 'Y'
             else 'N'
        end) as MAX_AMT_IND
from . . .;

【讨论】:

谢谢戈登。但我不能使用 rank desc 或 rank asc 因为我必须在最后考虑 Rank 0。所以顺序是Rank 1,Rank 2,Rank 3,Rank 4,Rank 5,然后是Rank 0。 @Niki 。 . .我不知道你的评论指的是什么。上面的查询应该只为您希望它用于 OP 中的数据的一行返回“Y”。 很抱歉,如果它令人困惑。让我这样说。 ID RANK AMT MAX_AMT_IND 13786 0 6.11 N 13786 1 6.11 Y 13786 2 6.11 N 如果所有三个记录的数量相同,则 max_amt_ind 应该是排名 1 的“Y”和其他两个记录的“N”。【参考方案2】:

我只在最近的活动中注意到了这个话题,但由于显然还没有以一种被认为可以接受的方式回答,我想我会提供一个尝试,尽管 OP 已经很老了。

忽略如何处理位于 1 到 5 的 rank-column 值之外但发现 rank-column 值为 0 的重复 max(amt) 值的可能性,以下似乎可能是至少两个测试用例的有效解决方案[一个在 OP 中,另一个在响应答案的评论中]:

设置:

 create table table_1                     
 ( id        int                          
 , rank      dec(2)                       
 , amt       dec(5, 2)                    
 , max_payer_ind for mpi char default null
 )                                        
 ;
 insert into  table_1 values          
   ( 11786 , 0  ,    6.11  , default )
 , ( 11786 , 1  ,    6.11  , default )
 , ( 12786 , 0  ,    6.11  , default )
 , ( 12786 , 1  ,    6.11  , default )
 , ( 12786 , 2  ,    6.11  , default )
 , ( 13786 , 0  ,    6.11  , default )
 , ( 13786 , 1  ,    2.9   , default )
 , ( 13786 , 2  ,    6.11  , default )
 ;

来自 OP 的原始查询被修改为在 CASE 表达式 [不是 CASE 语句] 中使用标量子选择,以根据名为 RANK 的列分配所需的值;使用带有三个不同 AMT 值的三行 id=13786 的原始示例,但添加第二个示例,其中两行相同的 AMT 值用于 id=11786,并添加第三个示例 [在评论 @Niki 2014 年 11 月 7 日中描述at 20:19] id=12786 的三行相同的 AMT 值。

 select a.id, a.rank, a.amt, b.max_amount             
      , case a.rank when ( select min(nullif(rank, 0))
                           from table_1               
                           where id=a.id              
                             and amt=b.max_amount   ) 
                    then 'Y' else 'N'                 
        end as max_amt_ind                            
 from Table_1 a                                       
 inner join table                                     
      ( select id, max(amt) as max_amount             
        from Table_1                                  
        where max_payer_ind is null                   
          and id = a.id                               
        group by id                                   
      ) b                                             
   on a.id = b.id                                     
 -- report from above query follows:
       ID   RANK     AMT   MAX_AMOUNT  MAX_AMT_IND
   11,786     0     6.11       6.11         N     
   11,786     1     6.11       6.11         Y     
   13,786     0     6.11       6.11         N     
   13,786     1     2.90       6.11         N     
   13,786     2     6.11       6.11         Y     
   12,786     0     6.11       6.11         N     
   12,786     1     6.11       6.11         Y     
   12,786     2     6.11       6.11         N     

现在考虑到重复的 max(amt) 在ranking=0 和ranking>5 中,以便使指标的分配有意义,“我们需要考虑最低排名(按顺序1,2,3,4,5 然后 0)”,我为测试用例提供了以下附加数据,并对查询进行了以下修订:

 insert into  table_1 values          
   ( 17786 , 0  ,    6.11  , default )
 , ( 17786 , 1  ,    1.11  , default )
 , ( 17786 , 2  ,    2.11  , default )
 , ( 17786 , 3  ,    3.11  , default )
 , ( 17786 , 4  ,    4.11  , default )
 , ( 17786 , 5  ,    5.11  , default )
 , ( 17786 , 6  ,    6.11  , default )

查询更改以启用与 a.rank=0 的匹配 [使用 IFNULL()] 并消除将指示分配给超过 5 的排名的考虑 [通过为标量子选择添加谓词 rank<=5]:

 select a.id, a.rank, a.amt, b.max_amount                  
      , case a.rank when ifnull(                           
                         ( select min(nullif(rank, 0))     
                           from table_1                    
                           where id=a.id                   
                             and rank<=5                   
                             and amt=b.max_amount   ) , 0 )
                    then 'Y' else 'N'                      
        end as max_amt_ind                                 
 from Table_1 a                          
 inner join table                        
      ( select id, max(amt) as max_amount
        from Table_1                     
        where max_payer_ind is null      
          and id = a.id                  
        group by id                      
      ) b        
   on a.id = b.id
 -- report from above query follows:
       ID   RANK     AMT   MAX_AMOUNT  MAX_AMT_IND
   11,786     0     6.11       6.11         N     
   11,786     1     6.11       6.11         Y     
   17,786     0     6.11       6.11         Y     
   17,786     1     1.11       6.11         N     
   17,786     2     2.11       6.11         N     
   17,786     3     3.11       6.11         N     
   17,786     4     4.11       6.11         N     
   17,786     5     5.11       6.11         N     
   17,786     6     6.11       6.11         N     
   13,786     0     6.11       6.11         N     
   13,786     1     2.90       6.11         N     
   13,786     2     6.11       6.11         Y     
   12,786     0     6.11       6.11         N     
   12,786     1     6.11       6.11         Y     
   12,786     2     6.11       6.11         N     

所以在上面的结果中,我们并没有用重复的 max(amt) 值指示rank=6,但是我们最终有一个案例,rank=0 实际上可以满足指示;也就是说,如果重复的 max(amt) 不在 1 到 5 的范围之外,则永远不会有机会指示 rank=0 ——也就是说,如果我理解问题描述的话。

【讨论】:

以上是关于DB2 Case Statement - 如果最大值相同,则选择最小值的主要内容,如果未能解决你的问题,请参考以下文章

DB2 中的 CASE 子句语句

DB2 xmlquery如何使用case语句默认空记录

db2 中 CASE 表达式中的子查询

Case Statement 麻烦的地方

SQL Server存储过程:if variable = X,case where statement

Prepared Statement 因 DB2 SQL 错误而失败