【问题标题】:SQL Syntax To Aggregate Records Based on Field Criteria and Output Total Record Counts基于字段标准和输出总记录计数聚合记录的 SQL 语法
【发布时间】:2017-01-28 20:36:00
【问题描述】:

SQL 查询返回如下所示的表结果:

下面列出了我当前运行的用于生成此表的 SQL:

SELECT DISTINCT 
    ld.LOAD_ID, lf.ACTUAL_DELIVERY_TS, ld.ORIG_LOC_ID, 
    fsd.PO_TYPE_CODE, fsf.CASE_QTY, 
    CASE 
       WHEN ORIG_LOC_ID IN (6903, 6909, 6912, 7100, 7101, 7183, 7184, 7837, 7840, 7976) 
          THEN 'Centerpoint'
       WHEN ORIG_LOC_ID IN (6061, 6088, 6060, 7042, 7078, 7085, 7086, 7084, 7089, 7093, 7094, 4892, 7628) 
          THEN 'Imports'
       WHEN ORIG_LOC_ID IN (8092, 8098, 9153, 9193, 9195, 9196) 
          THEN 'Returns'
       WHEN ORIG_LOC_ID IN (6005, 6007, 6008, 6014, 6022, 6029, 6041) 
          THEN 'Fashion'
       WHEN ORIG_LOC_ID IN (7006, 7356, 6280, 8240, 8103, 7853, 7005) 
          THEN 'eCom'
       WHEN ORIG_LOC_ID IN (6006, 6009, 6010, 6011, 6012, 6016, 6017, 6018, 6019, 6020, 6021, 6023, 6024, 6025, 6026, 6027, 6030, 6031, 6035, 6036, 6037, 6038, 6039, 6040, 6043, 6048, 6054, 6066, 6068, 6069, 6070, 6080, 6092, 6094, 7026, 7033, 7034, 7035, 7036, 7038, 7039, 7045) 
          THEN 'Regional'
       WHEN ORIG_LOC_ID IN (6042, 6047, 6055, 6056, 6057, 6059, 6062, 6064, 6065, 6071, 6072, 6073, 6074, 6077, 6082, 6083, 6084, 6085, 6090, 6091, 6095, 6096, 6097, 6099, 7010, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7021, 7023, 7024, 7025, 7030, 7047, 7048, 7053, 7055, 7068, 7070, 7077, 7079) 
          THEN 'Grocery'
       WHEN ORIG_LOC_TYPE_CODE IN ('VNDR') 
          THEN 'VNDR'
       WHEN ORIG_LOC_TYPE_CODE IN ('STORE') 
          THEN 'STORE'
    END AS LOADORIG, 
    CASE
       WHEN PO_TYPE_CODE IN (23, 33, 3, 53, 45, 73, 93) THEN 'DA'
       WHEN PO_TYPE_CODE IN (20, 22, 28, 29, 40, 42, 50, 83) THEN 'SS'
       WHEN PO_TYPE_CODE IN (10, 11, 12, 13, 14, 15, 16, 17, 18, 19) THEN 'Fashion'
       WHEN PO_TYPE_CODE IN (43) THEN 'XDOCK'
    END AS CHANNEL, 
    ld.DEST_LOC_ID
FROM 
    us_trans_dm_vm.LOAD_DIM ld, 
    us_trans_dm_vm.LOAD_FACT lf, 
    us_trans_dm_vm.FREIGHT_SHIPMENT_FACT fsf, 
    us_trans_dm_vm.FREIGHT_SHIPMENT_DIM fsd
WHERE 
    ld.LOAD_SK_ID = lf.LOAD_SK_ID
    AND lf.LOAD_SK_ID = fsf.LOAD_SK_ID
    AND fsf.SHIPMENT_SK_ID = fsd.SHIPMENT_SK_ID
    AND fsd.CURRENT_IND = 'Y'
    AND ld.CURRENT_IND = 'Y'
    AND ld.DEST_LOC_ID IN (6006, 6009, 6010, 6011, 6012, 6016, 6017, 6018, 6019, 6020, 6021, 6023, 6024, 6025, 6026, 6027, 6030, 6031, 6035, 6036, 6037, 6038, 6039, 6040, 6043, 6048, 6054, 6066, 6068, 6069, 6070, 6080, 6092, 6094, 7026, 7033, 7034, 7035, 7036, 7038, 7039, 7045)
    AND lf.ACTUAL_DELIVERY_TS BETWEEN '2016-02-01 00:00:00' AND '2016-07-31 23:59:59'

LOAD_ID 是唯一的记录标识符,每个 LOAD_ID 都有不同的 PO 类型和与之关联的案例计数。我试图找到一种方法来根据 PO 类型和案例计数的一些标准聚合 LOAD_ID 行:

例如 - 如果 PO_TYPE_CODE 20 的 CASE_QTY 大于与该 LOAD_ID 关联的总 CASE_QTY 的 50%,则将 LOAD_ID 30604179 计为“TEST”

如果 PO_TYPE_CODE 33 的 CASE_QTY 大于与该 LOAD_ID 关联的总 CASE_QTY 的 25%,则将 LOAD_ID 30604179 计为“TEST 2”

期望的输出:

任何帮助或指导将不胜感激!!!!

【问题讨论】:

  • 我删除了不兼容的数据库标签。请添加回您真正使用的数据库的标签。
  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(20 多年前),不鼓励使用它

标签: sql syntax teradata


【解决方案1】:

如果您的标准始终基于与 LOAD_ID 关联的总 CASE_QTY,我认为您只需要加入该结果,以便您可以比较每个值,例如:

SELECT DISTINCT 
    ld.LOAD_ID, ... fsf.CASE_QTY, 100.00 * CASE_QTY/sum_caseQty AS loadCaseQtyPct,
    ...
FROM 
    us_trans_dm_vm.LOAD_DIM ld INNER JOIN
    us_trans_dm_vm.LOAD_FACT lf ON
        ld.LOAD_SK_ID = lf.LOAD_SK_ID INNER JOIN
    us_trans_dm_vm.FREIGHT_SHIPMENT_FACT fsf ON
     lf.LOAD_SK_ID = fsf.LOAD_SK_ID INNER JOIN  
    us_trans_dm_vm.FREIGHT_SHIPMENT_DIM fsd ON
     fsf.SHIPMENT_SK_ID = fsd.SHIPMENT_SK_ID INNER JOIN
     (SELECT
     loadid, SUM(case_qty) AS sum_caseQty
     FROM
     us_trans_dm_vm.LOAD_DIM
     GROUP BY 1) cq ON
     ld.loadid = cq.loadid
WHERE 
     fsd.CURRENT_IND = 'Y'
    AND ld.CURRENT_IND = 'Y'
    AND ld.DEST_LOC_ID IN (6006, 6009, 6010, 6011, 6012, 6016, 6017, 6018, 6019, 6020, 6021, 6023, 6024, 6025, 6026, 6027, 6030, 6031, 6035, 6036, 6037, 6038, 6039, 6040, 6043, 6048, 6054, 6066, 6068, 6069, 6070, 6080, 6092, 6094, 7026, 7033, 7034, 7035, 7036, 7038, 7039, 7045)
    AND lf.ACTUAL_DELIVERY_TS BETWEEN '2016-02-01 00:00:00' AND '2016-07-31 23:59:59'

【讨论】:

    【解决方案2】:

    您可以使用窗口函数来解决这个问题。比如:

     CASE 
        WHEN POT_TYPE_CODE = 20 AND Cast(CASE_QTY AS DECIMAL(4,2)/SUM(CAST(CASE_QTY AS DECIMAL(4,2)) OVER (PARTITION BY LOAD_ID) > .5 
            THEN 'Test' 
        WHEN PO_TYPE_CODE = 33 AND Cast(CASE_QTY AS DECIMAL(4,2)/SUM(CAST(CASE_QTY AS DECIMAL(4,2)) OVER (PARTITION BY LOAD_ID) > .25 
            THEN 'Test 2' 
        END as my_new_field
    

    该窗口函数Sum(Case_QTY) OVER (PARTITION BY LOAD_ID) 将汇总中间结果集中该 load_id 的所有行并返回结果。将当前记录划分为 case_qty 为您提供可以测试的百分比。

    另外,我将 case_qty 转换为十进制以确保除法的结果是十进制。否则它可能会四舍五入到整数...不记得如何计算,所以它可能是不必要的。

    【讨论】:

    • 运行此程序时出现 3706 错误(预计在 ')' 和 '/' 之间存在)。我曾尝试调整这些 WHEN 语句的括号,但没有运气。这里有关于语法的任何想法吗?我不熟悉分区语法。否则我认为它会很好用
    • 看起来我没有在第一个演员表上加上括号。这是我看到的唯一不正常的东西。我现在在手机上,所以很难说。
    【解决方案3】:

    @JNevill

    我已经根据我需要的输出调整了窗口函数。我不再需要使用上述 50%/25% 标准来解决问题。相反,我使用窗口函数计算每行的 Case_QTY 百分比,与整个 Load_ID 的 Case_Qty 相比。我现在得到如下图所示的结果。

    使用此 SQL:

    SELECT 
    DISTINCT ld.LOAD_ID,lf.ACTUAL_DELIVERY_TS,ld.ORIG_LOC_ID,fsd.PO_TYPE_CODE,fsf.CASE_QTY,
    
    CASE 
    WHEN ORIG_LOC_ID IN (6903,6909,6912,7100,7101,7183,7184,7837,7840,7976) THEN 'Centerpoint'
    WHEN ORIG_LOC_ID IN (6061,6088,6060,7042,7078,7085,7086,7084,7089,7093,7094,4892,7628) THEN 'Imports'
    WHEN ORIG_LOC_ID IN (8092,8098,9153,9193,9195,9196) THEN 'Returns'
    WHEN ORIG_LOC_ID IN (6005,6007,6008,6014,6022,6029,6041) THEN 'Fashion'
    WHEN ORIG_LOC_ID IN (7006,7356,6280,8240,8103,7853,7005) THEN 'eCom'
    WHEN ORIG_LOC_ID IN (6006, 6009, 6010, 6011, 6012, 6016, 6017, 6018, 6019, 6020, 6021, 6023, 6024, 6025, 6026, 6027, 6030, 6031, 6035, 6036, 6037, 6038, 6039, 6040, 6043, 6048, 6054, 6066, 6068, 6069, 6070, 6080, 6092, 6094, 7026, 7033, 7034, 7035, 7036, 7038, 7039, 7045) THEN 'Regional'
    WHEN ORIG_LOC_ID IN (6042, 6047, 6055, 6056, 6057, 6059, 6062, 6064, 6065, 6071, 6072, 6073, 6074, 6077, 6082, 6083, 6084, 6085, 6090, 6091, 6095, 6096, 6097, 6099, 7010, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7021, 7023, 7024, 7025, 7030, 7047, 7048, 7053, 7055, 7068, 7070, 7077, 7079) THEN 'Grocery'
    WHEN ORIG_LOC_TYPE_CODE IN ('VNDR') THEN 'VNDR'
    WHEN ORIG_LOC_TYPE_CODE IN ('STORE') THEN 'STORE'
    END AS LOADORIG, 
    
    CASE
    WHEN PO_TYPE_CODE IN (23,33,3,53,45,73,93) THEN 'DA'
    WHEN PO_TYPE_CODE IN (20,22,28,29,40,42,50,83) THEN 'SS'
    WHEN PO_TYPE_CODE IN (10,11,12,13,14,15,16,17,18,19) THEN 'Fashion'
    WHEN PO_TYPE_CODE IN (43) THEN 'XDOCK'
    END AS CHANNEL,
    
    
    CASE 
    WHEN Channel = 'DA' THEN  CAST (CASE_QTY AS DECIMAL(38,0))/SUM(CAST(CASE_QTY AS DECIMAL(38,2))) OVER (PARTITION BY ld.LOAD_ID)
    WHEN Channel = 'SS' THEN  CAST (CASE_QTY AS DECIMAL(38,0))/SUM(CAST(CASE_QTY AS DECIMAL(38,2))) OVER (PARTITION BY ld.LOAD_ID)
    END AS New_Column,
    
    ld.DEST_LOC_ID
    
    FROM us_trans_dm_vm.LOAD_DIM ld,
                 us_trans_dm_vm.LOAD_FACT lf,
                 us_trans_dm_vm.FREIGHT_SHIPMENT_FACT fsf,
                 us_trans_dm_vm.FREIGHT_SHIPMENT_DIM fsd
    
    WHERE ld.LOAD_SK_ID = lf.LOAD_SK_ID
    AND lf.LOAD_SK_ID = fsf.LOAD_SK_ID
    AND fsf.SHIPMENT_SK_ID = fsd.SHIPMENT_SK_ID
    AND fsd.CURRENT_IND = 'Y'
    AND ld.CURRENT_IND = 'Y'
    AND ld.DEST_LOC_ID IN (6006)
    AND lf.ACTUAL_DELIVERY_TS BETWEEN '2016-07-20 00:00:00' AND '2016-07-31 23:59:59'
    
    GROUP BY ld.LOAD_ID,lf.ACTUAL_DELIVERY_TS,ld.ORIG_L
    

    如您所见,“新列”显示每个 Load_Id 的正确百分比,总和为 100%。现在我想按他们的频道和百分比汇总所有唯一的 Load_ID。

    例子:

    我一直在尝试使用类似的东西:

    SUM(CASE WHEN Channel = 'DA' THEN Percentage ELSE 0 END) TotalDACases,
    SUM(CASE WHEN Channel = 'SS' THEN Percentage ELSE 0 END) TotalStapleCases,
    

    或者:

    SUM(CASE WHEN Channel = 'DA' THEN  CAST (CASE_QTY AS DECIMAL(38,0))/SUM(CAST(CASE_QTY AS DECIMAL(38,2))) OVER (PARTITION BY ld.LOAD_ID) END) Test,
    SUM (CASE WHEN Channel = 'SS' THEN  CAST (CASE_QTY AS DECIMAL(38,0))/SUM(CAST(CASE_QTY AS DECIMAL(38,2))) OVER (PARTITION BY ld.LOAD_ID) END) Test2,
    

    但我收到一个错误(“无法嵌套有序分析函数”),我认为这与我嵌套 sum 函数有关。

    任何想法都会很棒!

    【讨论】:

    • 不能嵌套在 group by 中。原因是它们在初始聚合返回的结果集之上进行计算。相反,您必须执行上面的初始大查询,然后将该野兽粘在子查询中并在它之外进行进一步的聚合。此外,由于这更像是一个新问题,因此最好将其放在一个关于 SO 的新问题中,因为这不是“答案”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    • 2020-05-26
    • 2015-06-11
    相关资源
    最近更新 更多