TERADATA从滚动SUM限制创建组ID

时间:2013-09-05 16:07:57

标签: sql group-by sum teradata

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

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

我创建了一个case语句来创建我需要的输出,但如果我想将group id cutoff从50改为100,或者如果我得到更多的产品和数量,我必须不断更改case语句。是否有一种简单的方法可以使用递归或其他方法来容纳这个? 这适用于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 ;

4 个答案:

答案 0 :(得分:0)

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

Psuedo创建:

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_nbr表添加'group_id'并使group_id 1成为一组运行限制并且group_id为2,3,4,5等具有不同的运行限制集并使用where子句来允许多个group_nbr设置选择您要使用的group_id。

答案 1 :(得分:0)

希望下面的逻辑有帮助,如果它的增量为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 :(得分:0)

这是我在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
;

答案 3 :(得分:0)

当我第一次看到你的问题时,我认为这是一种装箱问题。但您的查询似乎只是想将数据放入 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)。