1

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

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 ;
4

4 回答 4

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)。

于 2013-09-17T10:14:54.847 回答
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
;
于 2013-09-17T01:37:43.463 回答
0

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

伪创建:

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。

于 2013-09-05T16:30:37.850 回答
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 ;
于 2013-09-05T16:32:36.827 回答