返回group(min / max)结果的oracle case语句

时间:2015-04-17 00:41:57

标签: oracle11g group-by case

我正在创建一个case语句,根据具体情况返回最小或最大日期字段。

由于案例中有组函数,我认为我需要将部分或全部语句放在逐个组中,但是我收到错误" ORA-00934:此处不允许组函数&# 34;当我试图把它放在一个小组中时。

我也尝试基于相同的case语句加入另一个表,但似乎也没有用。

以下是"违规"案例陈述:

  

情况下           当id.DISC_PGM_NUM在(' 15B',' 20B',' 25B​​',' 24B',' 28B' ,! 33B')然后是max(cn.CN_DATE)           else min(cn.CN_DATE)以Open_dt结束,

以下是完整查询:

SELECT DISTINCT
        id.CUST_ID,  
        case
          when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then 'Flex Bundle'
            when id.UDAC_CODE = 'ELB1' then 'ELB1'
            when id.UDAC_CODE = 'ELB2' then 'ELB2'
            when id.UDAC_CODE in ('GAT2', 'GAT1W','START', 'STARTW') then 'Smart Start Bundle'
                  else 'Unknown'
            end as ProgramName,         
        case
             when CN.SIGN_TYPE = 'U' then ' 920'
            else id.DIV_NUM end as Div,
        case
            when CN.SIGN_TYPE = 'U' then '0920'
            else id.UNIT_NUM end as Unit,        
        case 
            when CN.SIGN_TYPE = 'U' then 9200
            else id.SALES_REP_ID end as Rep_ID,
        case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end as  Open_dt,            
         extract(year from case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end) as Yr,      
        To_Number(to_char(case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end,'IW'), '99') as  Wk, 
        sum(id.ITEM_NISD_AMT) as BundleNI   

    from 
        ICV.VZ_ITEM_DETAIL                            id
        join ICV.VZ_CUSTOMER                   vc  on (vc.CUSTOMER_ID = id.CUST_ID)
        left outer join (
            select  CUSTOMER_ID, PRODUCT_CODE, PRODUCT_ISSUE_NUM, min(CONTRACT_DATE) as CN_date, SIGN_TYPE
            from    VAST.CONTRACT                      
            where 
            SIGN_TYPE not in ( 'U', 'M', '-', 'C', 'L')
            group by   CUSTOMER_ID, PRODUCT_CODE, PRODUCT_ISSUE_NUM,  sign_type) cn
        on (ID.CUST_ID = CN.CUSTOMER_ID and ID.DIR_NUM = CN.PRODUCT_CODE 
                                                                        and id.DIR_ISSUE_NUM = cn.PRODUCT_ISSUE_NUM)
           where 
        (id.UDAC_CODE in ('ELB1', 'ELB2', 'GAT2', 'GAT1W','START', 'STARTW')
        or id.DISC_PGM_NUM in ('15B','20B','25B','24B','28B','33B'))
        and id.DIV_NUM in ('  C2', '  C3', '  C4', '  C6', '  N1', '  N2', ' 371', '  K3', '  K1', '  K2' , ' 275', ' 253', ' 368', ' 296')
        and id.ITEM_ACTION_CODE in ('A', 'I')
           and id.PAY_PERIOD_YR= '2015'
        and vc.SOURCE_SYSTEM_CDE= 'V'
        and id.HANDLED_PAY_PERIOD_YR is not null
        and HANDLED_PAY_PERIOD_NUM >=6

    group by
        id.CUST_ID,   
        case
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then 'Flex Bundle'
            when id.UDAC_CODE = 'ELB1' then 'ELB1'
            when id.UDAC_CODE = 'ELB2' then 'ELB2'
            when id.UDAC_CODE in ('GAT2', 'GAT1W','START', 'STARTW') then 'Smart Start Bundle'
            else 'Unknown'
            end,         
        case
             when CN.SIGN_TYPE = 'U' then ' 920'
            else id.DIV_NUM end,
        case
            when CN.SIGN_TYPE = 'U' then '0920'
            else id.UNIT_NUM end,        
        case 
            when CN.SIGN_TYPE = 'U' then 9200
            else id.SALES_REP_ID end,    
            case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end,            
         extract(year from case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end),      
        To_Number(to_char(case 
            when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)
            else min(cn.CN_DATE) end,'IW'), '99')  

这可能吗?

2 个答案:

答案 0 :(得分:0)

您可以在CASE的THEN部分使用单行子查询执行您想要的操作。 例如。

SELECT
CASE
WHEN  id.DISC_PGM_NUM IN ('15B','20B','25B','24B','28B','33B')
THEN 
(
SELECT MAX(cn.CN_DATE) FROM <table_name> cn
)
ELSE
(
SELECT MAX(cn.CN_DATE) FROM <table_name> cn
)
END AS Open_dt
FROM ....

希望你能得到解决方案。

答案 1 :(得分:0)

如果没有让您的架构进行测试,那么很难完全写出您的大型查询。但是这样的事情是行不通的:

when id.DISC_PGM_NUM in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)

它不起作用,因为DISC_PGM_NUM没有被分组。

现在,如果您聚合DISC_PGM_NUM,它可以工作。像这样:

when max(id.DISC_PGM_NUM) in  ('15B','20B','25B','24B','28B','33B') then max(cn.CN_DATE)

问题在于max(id.DISC_PGM_NUM)不会为您提供您正在寻找的价值。如果记录具有值&#39; 15B&#39;和&#39; 40B&#39;,&#39; 40B&#39;将是你的最大值,所以它不符合IN条款。解决此问题的一种方法是使用DECODE或其他CASE语句。

例如:

when max(case when id.DISC_PGM_NUM in ('15B','20B','25B','24B','28B','33B') then 1 else 0 end) = 1 then max(cn.CN_DATE)

这会将您想要的所有值都视为1,将其他值视为0,以便您的最大值得到正确评估。

查看此SQLFiddle:http://sqlfiddle.com/#!4/a330e/10