将一行拆分为多行 - Teradata

Split a row into multiple rows - Teradata

下面是我的例子 table

Names   Start_Date   Orders    Items
AAA     2020-01-01   300       100
BAA     2020-02-01   896       448

我的要求如下

Names   Start_Date   Orders   
AAA     2020-01-01   100   
AAA     2020-01-01   100
AAA     2020-01-01   100
BBB     2020-02-01   448
BBB     2020-02-01   448

应根据 (Orders/Items) 值拆分行

这需要递归 CTE。这是我的处理方式,对一些示例数据使用可爱的 volatile table。

    create volatile table vt_foo
    (names varchar(100), start_date date, orders int, items int)
    on commit preserve rows;

    insert into vt_foo values ('AAA','2020-01-01',300,100);
    insert into vt_foo values ('BAA','2020-02-01',896,448);
    insert into vt_foo values ('CCC','2020-03-01',525,100);  -


    with recursive cte (names, start_date,items, num, counter) as (
    select
    names,
    start_date,
    items,
round(orders /( items * 1.0) ) as num ,
    1 as counter
    from vt_foo
    UNION ALL
    select
    a.names,
    a.start_date,
    a.items,
    b.num,
    b.counter + 1
    from vt_foo a
    inner join cte b 
    on a.names = b.names
    and a.start_date =b.start_date
    where b.counter + 1 <= b.num
    )
    select  * from cte
    order by names,start_date

此位:b.counter + 1 <= b.num 是将输出限制为每个 product/date 的正确行数的关键。

我觉得应该没问题,但是用少量数据测试一下。

Teradata SQL 扩展创建时间序列(基于@Andrew 的测试数据)是一个很好的任务:

SELECT *
FROM vt_foo
EXPAND ON PERIOD(start_date, start_date + Cast(Ceiling(Cast(orders AS FLOAT)/items) AS INT)) AS pd 

要将订单精确拆分为商品:

SELECT dt.*, 
   CASE WHEN items * (end_date - start_date) > orders 
        THEN orders MOD items
        ELSE items
   end
FROM
 (
   SELECT t.*, End(pd) AS end_date
   FROM vt_foo AS t
   EXPAND ON PERIOD(start_date, start_date + Cast(Ceiling(Cast(orders AS FLOAT)/items) AS INT)) AS pd 
 ) AS dt