聚合 in case 语句并出现 "not a GROUP BY expression" 错误

Aggregate in case statement with "not a GROUP BY expression" error

为什么在我的查询中包含以下 case 语句时出现“不是 GROUP BY 表达式”错误,即使下面的 case 语句使用了 GROUP BY 中不允许的聚合? 当我在 GROUP BY 中包含 case 语句时,当然会出现“此处不允许使用组函数”错误,但是当我将其从 GROUP BY 中删除时,我会再次出现“不是 GROUP BY 表达式”错误。

谁能解释一下,好吗?提前致谢!

        ,case
                when
                        round(sum(i.INVOICE_AMOUNT))  > 50000 and 
                        (cont_all.CONTRACT_EFFECTIVE_DATE > '&end_date'
                        or cont_all.CONTRACT_EXPIRATION_DATE <= '&end_date'
                        or cont_all.CONTRACT_EFFECTIVE_DATE is null) 
                        then 'Over 50k and no Contract'
                else 'Contract or No Contract with spend below 50k'
                end as "Contract Needed?"

这是 mathguy 建议的完整查询:

define end_date = '30-SEP-20'

    select
             v.SEGMENT1 "Vendor Number"
            ,v.VENDOR_NAME "Vendor Name"
            ,s.VENDOR_SITE_CODE "Site Name"
            ,case
                    when s.ORG_ID in ('285',    '296',  '294',  '327',  '304',  '297',  '295',  '312',  '313',  '315',  '319',  '322',  '321',  '306') then 'Fleet'
                    else 'Non-Fleet'
                    end as "Fleet / Non-Fleet"
            ,case
                    when s.ORG_ID in ('288','325','285') then 'Belgium'
                    when s.ORG_ID in ('301','296','302','294') then 'Germany'
                    when s.ORG_ID in ('327','305','304') then 'Spain'
                    when s.ORG_ID in ('298','303','297','299','300','295') then 'France'
                    when s.ORG_ID in ('309','307') then 'Ireland'
                    when s.ORG_ID in ('316','312','314','317','313') then 'Italy'
                    when s.ORG_ID in ('318','315') then 'Luxembourg'
                    when s.ORG_ID in ('318','315') then 'Monaco'
                    when s.ORG_ID in ('322','323','324','326','321') then 'Netherlands'
                    when s.ORG_ID in ('308','310','311','306') then 'United Kingdom'
                    else 'Error'
                    end as "Country"
            ,o.NAME "Operating Unit"
            ,to_number(round(sum(i.INVOICE_AMOUNT))) "Spend last 12 months"
            ,case
                    when round(sum(i.INVOICE_AMOUNT))  > 50000 then 'Over 50,000'
                    when round(sum(i.INVOICE_AMOUNT))  <= 50000 then 'Below 50,000'
                    when round(sum(i.INVOICE_AMOUNT))  = 0 then 'No spend'
                    when round(sum(i.INVOICE_AMOUNT))  is null then 'No spend'
                    else 'Wrong'
                    end as "Spend brackets last 12 months"
            ,case
                    when cont_all.CONTRACT_EFFECTIVE_DATE <='&end_date' then 'Contract'
                    when cont_all.CONTRACT_EFFECTIVE_DATE > '&end_date' then 'No Contract'
                    when cont_all.CONTRACT_EXPIRATION_DATE <= '&end_date' then 'No Contract'
                    when cont_all.CONTRACT_EXPIRATION_DATE > '&end_date' then 'Contract'
                    when cont_all.CONTRACT_EFFECTIVE_DATE is null then 'No Contract'
                    else 'Wrong'
                    end as "Contract Indicator"
--            ,case
--                    when
--                            round(sum(i.INVOICE_AMOUNT))  > 50000 and 
--                            (cont_all.CONTRACT_EFFECTIVE_DATE > '&end_date'
--                            or cont_all.CONTRACT_EXPIRATION_DATE <= '&end_date'
--                            or cont_all.CONTRACT_EFFECTIVE_DATE is null) 
--                            then 'Over 50k and no Contract'
--                    else 'Contract or No Contract with spend below 50k'
--                    end as "Contract Needed?"
            ,t.NAME "Terms"
            ,TO_CHAR(TO_DATE('&end_date', 'DD-MON-YYYY'), 'Mon YY') Month
            
from
            AP.AP_SUPPLIERS v
            join AP.AP_SUPPLIER_SITES_ALL s on v.VENDOR_ID=s.VENDOR_ID
            join apps.HR_ALL_ORGANIZATION_UNITS o on s.ORG_ID=o.ORGANIZATION_ID 
            left join AP.AP_INVOICES_ALL i on s.VENDOR_SITE_ID=i.VENDOR_SITE_ID
            left join AP_TERMS_TL t on s.TERMS_ID=t.TERM_ID
            left join APPS.OKC_REP_CONTRACT_PARTIES cont on v.VENDOR_ID=cont.PARTY_ID
            left join APPS.OKC_REP_CONTRACTS_ALL cont_all on cont.CONTRACT_ID=cont_all.CONTRACT_ID

where
            ((v.end_date_active is null or v.end_date_active > '&end_date') and (s.inactive_date is null or s.inactive_date > '&end_date'))
            and v.CREATION_DATE <= '&end_date'
            and s.ORG_ID in  ('324','288','325','285','301','296','302','294','327','305','304','298','303','297','299','300','295','309','307','316','312','314','317','313','318','315','320','319','322','323','326','321','308','310','311','306')
            and v.SEGMENT1 = 259456
            and i.CREATION_DATE between add_months('&end_date', -12) and '&end_date'
            and i.CANCELLED_DATE is null
                  
group by
            v.SEGMENT1
            ,v.VENDOR_NAME
            ,s.VENDOR_SITE_CODE
            ,case
                    when s.ORG_ID in ('285',    '296',  '294',  '327',  '304',  '297',  '295',  '312',  '313',  '315',  '319',  '322',  '321',  '306') then 'Fleet'
                    else 'Non-Fleet'
                    end
            ,case
                    when s.ORG_ID in ('288','325','285') then 'Belgium'
                    when s.ORG_ID in ('301','296','302','294') then 'Germany'
                    when s.ORG_ID in ('327','305','304') then 'Spain'
                    when s.ORG_ID in ('298','303','297','299','300','295') then 'France'
                    when s.ORG_ID in ('309','307') then 'Ireland'
                    when s.ORG_ID in ('316','312','314','317','313') then 'Italy'
                    when s.ORG_ID in ('318','315') then 'Luxembourg'
                    when s.ORG_ID in ('318','315') then 'Monaco'
                    when s.ORG_ID in ('322','323','324','326','321') then 'Netherlands'
                    when s.ORG_ID in ('308','310','311','306') then 'United Kingdom'
                    else 'Error'
                    end
            ,o.NAME
            ,case
                    when cont_all.CONTRACT_EFFECTIVE_DATE <='&end_date' then 'Contract'
                    when cont_all.CONTRACT_EFFECTIVE_DATE > '&end_date' then 'No Contract'
                    when cont_all.CONTRACT_EXPIRATION_DATE <= '&end_date' then 'No Contract'
                    when cont_all.CONTRACT_EXPIRATION_DATE > '&end_date' then 'Contract'
                    when cont_all.CONTRACT_EFFECTIVE_DATE is null then 'No Contract'
                    else 'Wrong'
                    end
--            ,case
--                    when
--                            (round(sum(i.INVOICE_AMOUNT))  > 50000
--                            and 
--                            (cont_all.CONTRACT_EFFECTIVE_DATE > '&end_date'
--                            or cont_all.CONTRACT_EXPIRATION_DATE <= '&end_date'
--                            or cont_all.CONTRACT_EFFECTIVE_DATE is null) )
--                            then 'Over 50k and no Contract'
--                    else 'Contract or No Contract with spend below 50k'
--                    end
            ,t.NAME
            ,TO_CHAR(TO_DATE('&end_date', 'DD-MON-YYYY'), 'Mon YY')

这是您的简化示例

create table  tab as
select 
1 SEGMENT1,
sysdate + rownum as CONTRACT_EFFECTIVE_DATE, rownum INVOICE_AMOUNT from dual 
connect by level <= 10;

select 
  SEGMENT1,
  case when sum(INVOICE_AMOUNT) > 50 and CONTRACT_EFFECTIVE_DATE > DATE'2020-01-01' then 'OK' else 'NOK' end as col1
from tab  
group by SEGMENT1;

这当然会导致 ORA-00979: not a GROUP BY expression 因为你 group by CONTRACT_EFFECTIVE_DATE

但是添加 CONTRACT_EFFECTIVE_DATE 很可能不是您想要的。

我想你需要把过滤条件 放入 聚合函数中,像这样 - 所以你只聚合 INVOICE_AMOUNT 如果条件是完整的并进行比较结果与阈值

select 
  SEGMENT1,
  case when 
      sum(case when CONTRACT_EFFECTIVE_DATE > DATE'2020-01-01'then INVOICE_AMOUNT end) > 50  
  then 'OK' else 'NOK' end as col1
from tab  
group by SEGMENT1;