【问题标题】:TERADATA Creating Group ID from Rolling SUM LimitTERADATA 从 Rolling SUM 限制创建组 ID
【发布时间】:2013-09-09 13:41:50
【问题描述】:

我有一个产品列表和一个与单个表中销售数量相对应的计数。数据布局如下:

Product Name  QTY_SOLD
Mouse            23
Keyboard         25
Monitor          56
TV               10
Laptop           45
...

我想创建一个组 ID,如果售出数量的 ROLLING 总和大于 50,则创建组。我们可以按产品名称订购以获得类似于以下的输出。

Product Name   QTY_SOLD   GROUP_NBR
Keyboard          25          1
Laptop            45          1
Monitor           56          2
Mouse             23          3
TV                10          3

我创建了一个案例语句来创建我需要的输出,但是如果我想将组 ID 截止值从 50 更改为 100,或者如果我获得更多产品和数量,我必须不断更改案例语句。有没有一种简单的方法可以使用递归或其他方法来适应这种情况? 这适用于 Teradata 13.10

UPDATE main FROM prod_list AS main,  
(  
SEL PROD_NAME
, QTY_SOLD
, SUM(QTY_SOLD) OVER (ORDER BY PROD_NAME ROWS UNBOUNDED PRECEDING) RUNNING  FROM prod_list   
) inr 
SET GROUP_NBR = CASE  
WHEN RUNNING < 50 THEN 1
WHEN RUNNING > 50 AND RUNNING < 100 THEN 2
WHEN RUNNING > 100 AND RUNNING < 150 THEN 3
WHEN RUNNING > 150 AND RUNNING < 200 THEN 4
WHEN RUNNING > 200 AND RUNNING < 250 THEN 5
ELSE 6  
END
WHERE main.PROD_NAME = inr.PROD_NAME ;

【问题讨论】:

    标签: sql group-by sum teradata


    【解决方案1】:

    当我第一次看到你的问题时,我认为这是一种装箱问题。但是您的查询看起来只是想将您的数据放入 n 个存储桶中:-)

    Teradata 支持 QUANTILE 函数,但它已被弃用,并且不符合您的要求,因为它会创建大小相等的存储桶。您需要 WIDTH_BUCKET 来创建(顾名思义)等宽的桶:

    SELECT 
        PROD_id
    ,   COUNT(DISTINCT PROD_ID) AS QTY
    ,   SUM(QTY) OVER (ORDER BY QTY ROWS UNBOUNDED PRECEDING) RUNNING
    ,   WIDTH_BUCKET(RUNNING, 1, 120*2000000, 120) AS GRP_NBR
    FROM TMP_WORK_DB.PROD_LIST
    GROUP BY 1
    

    您可以轻松更改存储桶的大小 (2000000) 或存储桶的数量 (120)。

    【讨论】:

    • 我从未见过该功能,但它运行良好。谢谢。
    【解决方案2】:

    创建一个引用表并加入它...然后只需要在一个表中完成更改(甚至可以创建一个过程来帮助稍后自动更改表)

    伪创建:

    Create table group_nbr (low_limit,upper_limit,group_nbr)
    

    将您的案例值插入该表并使用大于和小于条件对其进行内部连接。

    select *, group_nbr.group_nbr
    from table inner join group_nbr on RUNNING > lower_limit and RUNNING < upper_limit
    

    代码无法正常工作,因为它坐在那里,但希望您能很好地理解这个想法,以便将您的代码更改为它。我发现将这些值留在这样的参考表中比更改代码要容易得多。您甚至可以通过将“group_id”添加到 group_nbr 表并让 group_id 1 成为一组运行限制和 group_id 2、3、4、5 等具有不同组运行限制并使用 where 子句来允许多个 group_nbr 设置选择您要使用的 group_id。

    【讨论】:

    • 好主意。让我试试看。谢谢
    • 让我知道它是怎么回事......这里的逻辑应该适合你,它更多的是调整代码和使用它的问题。我真的建议将“group_id”列放在那里,因为它可以让您跟踪每个组的各种值...将使未来的报告和历史验证更容易一些。
    • 我创建了一个递归查询来填充 group_nbr 表,以便我可以根据需要调整间隔和限制。然后,我将 grp_nbr 表与正在运行的查询一起使用,并使用简单的 between 来设置组号。有时 qroup 数字不是连续的,但它仍然创建了我正在寻找的不同组。它就像一个魅力。谢谢。
    【解决方案3】:

    希望下面的逻辑有帮助,如果它的增量大约为 50。

    UPDATE main FROM prod_list AS main,  
    (  
    SEL PROD_NAME
    , QTY_SOLD
    , SUM(QTY_SOLD) OVER (ORDER BY PROD_NAME ROWS UNBOUNDED PRECEDING) RUNNING  FROM prod_list   
    ) inr 
    SET GROUP_NBR = RUNNING /50
    WHERE main.PROD_NAME = inr.PROD_NAME ;
    

    【讨论】:

    • 这并没有真正起作用,因为它仍然创建了奇数个组。使用上面的数据创建了 2 个组。我在 10 组上尝试了您的解决方案,但它仍然没有真正均匀地分配产品。但它给了我一个尝试的想法。
    • 我构建了这段代码,运行了超过 100 种产品,它几乎给了我想要的东西,但它并没有像我希望的那样均匀分布。
      UPDATE main FROM prod_list AS main, ( SEL PROD_NAME , QTY_SOLD , SUM(QTY_SOLD) OVER (ORDER BY NUMOF ROWS UNBOUNDED PRECEDING) RUNNING FROM prod_list ) inr SET GROUP_NBR = RUNNING MOD WHERE main.PROD_NAME = inr.PROD_NAME ;`
    【解决方案4】:

    这是我根据 Twelfth 的建议创建的代码。

    -- create the first entry for the recursive query
    INSERT  TMP_WORK_DB.GRP_NBRS VALUES (0,1,0,2000000);
    


    INSERT TMP_WORK_DB.GRP_NBRS (GRP_NBR,LOWER_LIMIT, UPPER_LIMIT)
    WITH RECURSIVE GRP_RECRSV (GRP_NBR, LOWER_LIMIT, UPPER_LIMIT) 
    AS (
    SELECT 
        1 AS GRP_NBR
    ,   LOWER_LIMIT
    ,   UPPER_LIMIT
    FROM TMP_WORK_DB.GRP_NBRS
    UNION ALL
    SELECT
        GRP_NBR + 1 
    ,   LOWER_LIMIT + 2000000 -- set the interval to 2 million
    ,   UPPER_LIMIT + 2000000 -- can be adjusted as needed
    FROM GRP_RECRSV
    WHERE GRP_NBR < 120 -- needed a limit so that it would not be endless
    )
    SELECT * FROM GRP_RECRSV
    ;
    


    -- delete the first entry because it was duplicated
    DELETE FROM TMP_WORK_DB.GRP_NBRS WHERE GRP_NBR = 0;
    
    -- set grp nbr using the limits table
    INSERT TMP_WORK_DB.PROD_LIST_GRP
    WITH NUMOFPRODS (PROD_NAME,QTY,RUNNING) AS
    (
        SELECT 
            PROD_NAME
        ,   COUNT(DISTINCT PROD_ID) AS QTY
        ,   SUM(QTY) OVER (ORDER BY QTY ROWS UNBOUNDED PRECEDING) RUNNING
        FROM TMP_WORK_DB.PROD_LIST
        GROUP BY 1
    )
    SELECT 
        PROD_NAME
    ,   QTY
    ,   RUNNING
    ,   GRP_NBR
    FROM NUMOFPRODS a
    JOIN TMP_WORK_DB.GRP_NBRS b ON RUNNING BETWEEN LOWER_LIMIT AND UPPER_LIMIT
    ;
    

    【讨论】:

      猜你喜欢
      • 2015-11-03
      • 1970-01-01
      • 2022-12-28
      • 1970-01-01
      • 2017-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多