【问题标题】:SQL (Teradata): Removing NULLs caused by GroupBy / CASE StatementSQL (Teradata):删除由 GroupBy / CASE 语句引起的 NULL
【发布时间】:2018-07-10 20:37:16
【问题描述】:

我的结果中出现 NULL 的问题。这是因为我如何将 Group By & CASE 声明与“ItemDamagedStatus”一起使用。一种解决方案可能是分解那些 CASE 语句项并对同一个表执行 JOIN。但是,当我这样做时,一些数据被丢弃了。

下面的查询实际上给了我正确的数字。我只是希望它根据以下内容汇总为一行:Product/Market/Group1。

想法?有问题吗?

SELECT   t1.Product
        , t1.Market 
        , t1.Group1                                            
        , COUNT(DISTINCT t1.ItemID ||'-'||t1.Date1) AS StoredMth
        , CASE WHEN t1.ItemDamagedStatus = 'C' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS CompleteDmgMth
        , CASE WHEN t1.ItemDamagedStatus = 'P' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS PartialDmgMth
        , CASE WHEN t1.ItemDamagedStatus = 'N' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS NotDmgMth
        , CASE WHEN t1.ItemRepairStatus = 'Y' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS RepairMth
FROM  MainDatabase.Items t1
WHERE  t1.Date1 BETWEEN '2017-01-01' AND '2017-12-31'
GROUP BY      t1.Product
            , t1.Market 
            , t1.Group1  
            , t1.ItemDamagedStatus
            , t1.ItemRepairStatus

我得到的结果:

Product Market Group1 StoredMth CompleteDmgMth PartialDmgMth NotDmgMth  RepairMth
Car     North  Y      950       50             NULL          NULL       75
Car     North  Y      NULL      NULL           100           NULL       NULL
Car     North  Y      NULL      NULL           NULL          800        NULL
Car     North  N      165       NULL           75            NULL       10
Car     North  N      NULL      NULL           NULL          90         NULL
Car     South  Y      1400      500            NULL          NULL       800
Car     South  Y      NULL      NULL           NULL          900        NULL

我想要的结果:

Product Market Group1 StoredMth CompleteDmgMth PartialDmgMth NotDmgMth  RepairMth
Car     North  Y      950       50             100           800        75
Car     North  N      165       NULL           75            90         10
Car     South  Y      1400      500            NULL          900        800

(只是一个跟进,以防万一这会让任何人失望或他们试图合并一些值......是的:CompleteDmgMth + PartialDmgMth + NotDmgMth = StoredMth,但它在我们的数据中并不是一直都非常准确,所以我们使用两种不同的方法。)

如果有些东西看起来很奇怪或框架不正确,我深表歉意,这是我第一次在这里发帖。

【问题讨论】:

    标签: sql group-by null case teradata


    【解决方案1】:

    使用聚合,但不是在所有列上。您可以将CASE 表达式嵌套在COUNT(DISTINCT) 中:

    SELECT t1.Product, t1.Market, t1.Group1,                                        
            COUNT(DISTINCT t1.ItemID || '-' || t1.Date1) AS StoredMth
            COUNT(DISTINCT CASE WHEN t1.ItemDamagedStatus = 'C' THEN t1.ItemID || '' || t1.Date1) END) AS CompleteDmgMth
            COUNT(DISTINCT CASE WHEN t1.ItemDamagedStatus = 'P' THEN t1.ItemID || '' || t1.Date1 END) AS PartialDmgMth
            COUNT(DISTINCT CASE WHEN t1.ItemDamagedStatus = 'N' THEN t1.ItemID || '-' || t1.Date1 END) AS NotDmgMth
            COUNT(DISTINCT CASE WHEN t1.ItemRepairStatus = 'Y' THEN t1.ItemID || '-' || t1.Date1 END) AS RepairMth
    FROM  MainDatabase.Items t1
    WHERE  t1.Date1 BETWEEN '2017-01-01' AND '2017-12-31'
    GROUP BY t1.Product, t1.Market, t1.Group1;
    

    【讨论】:

    • 太棒了!谢谢你,戈登,按我的需要工作!完全忘记了你可以在聚合函数中嵌套案例,哈哈。
    【解决方案2】:

    您可以使用 MAX 仅捕获非空值,而不是对这些字段进行分组:

    SELECT derived_table.Product,
    derived_table.Market
    , derived_table.Group1
    , MAX(derived_table.StoredMth) as StoredMth
    , MAX(derived_table.CompleteDmgMth) as CompleteDmgMth
    , MAX(derived_table.PartialDmgMth) as PartialDmgMth
    , MAX(derived_table.NotDmgMth) as NotDmgMth
    , MAX(derived_table.RepairMth) as RepairMth
    FROM (
    
    SELECT   t1.Product
            , t1.Market 
            , t1.Group1                                            
            , COUNT(DISTINCT t1.ItemID ||'-'||t1.Date1) AS StoredMth
            , CASE WHEN t1.ItemDamagedStatus = 'C' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS CompleteDmgMth
            , CASE WHEN t1.ItemDamagedStatus = 'P' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS PartialDmgMth
            , CASE WHEN t1.ItemDamagedStatus = 'N' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS NotDmgMth
            , CASE WHEN t1.ItemRepairStatus = 'Y' THEN COUNT(DISTINCT t1.ItemID ||'-'|| t1.Date1) END AS RepairMth
    FROM  MainDatabase.Items t1
    WHERE  t1.Date1 BETWEEN '2017-01-01' AND '2017-12-31'
    GROUP BY      t1.Product
                , t1.Market 
                , t1.Group1  
                , t1.ItemDamagedStatus
                , t1.ItemRepairStatus) as derived_table
    GROUP BY derived_table.Product,
    derived_table.Market
    , derived_table.Group1;
    

    【讨论】:

    • Greg 真快,谢谢!它大部分有效,但我知道如何解决确实出现的问题。 (StoredMth 的 MAX 是问题所在,如果 group by 包含 ItemDamagedStatus/ItemRepairStatus,它不应该是最大值——修复它的方法很多,但一种快速的方法是另一个专门用于 StoredMth 的派生表。)
    猜你喜欢
    • 2021-10-11
    • 2017-04-01
    • 1970-01-01
    • 2019-05-22
    • 2015-01-11
    • 2015-05-05
    • 1970-01-01
    • 2014-11-18
    • 2019-03-31
    相关资源
    最近更新 更多