如何基于列将行拆分为多个

时间:2019-09-03 03:38:56

标签: sql teradata

我必须根据一个计数列将一行分为多行。如果count为6,则行应拆分为2,第一行的计数为5,下一行为1。如果count为17,将进行4拆分,每3列的行数为5,最后一行为2。

表将包含2列:

    id    CNT
  ------------
    10    17

上一行应分成4个,如下所示:

    id    CNT
--------------------
    10    5
    10    5
    10    5
    10    2

我尝试使用mod和除法来查找拆分总数,但是找不到最终解决方案。

请提供您的意见以实现这一目标。

2 个答案:

答案 0 :(得分:2)

您可以尝试一下。我不确定teradata中使用的语法,但这肯定会使您了解如何解决问题。

首先,我们需要找到每个数字相对于id的商和余数部分。然后商就是您要重复循环的次数,为此我们使用recursive cte,余数是最后一行,需要添加最后一行以获得等于您的值的数字总和。

示例查询将是这样。

declare @tab table ( id int, num int )
insert into @tab ( id, num )
values ( 1, 17 )
, ( 2, 22 )

; with cte as (
select id, num , num %5 as remainder, num/5 as quo from @tab )
, ct (sl, id, num, val) as (
select 1 as sl, id, num, 5 as val from cte
union all
select c.sl+1, t.id, t.num, c.val from cte as t inner join ct as c on t.id=c.id where c.sl<t.quo
)
, cfinal (id, num, val) as (
select id, num, val from ct 
union all
select id, num, remainder from cte
)
select * from cfinal order by id, val desc

结果


id          num         val
----------- ----------- -----------
1           17          5
1           17          5
1           17          5
1           17          2
2           22          5
2           22          5
2           22          5
2           22          5
2           22          2


答案 1 :(得分:1)

DarkRob的递归查询可以简化为

WITH RECURSIVE cte AS
 (
   SELECT id
      -- remainder or 5 if no remainder
     ,CASE WHEN Cnt MOD 5 = 0 THEN 5 ELSE Cnt MOD 5 END AS val
      -- how many rows left?
     ,(Cnt - val) / 5 AS x
   FROM tab
   WHERE Cnt > 0

   UNION ALL

   SELECT id, 5, x -  1
   FROM cte
   WHERE x > 0
 )
SELECT * 
FROM cte

但是我更愿意(ab)使用Teradata的时间序列扩展功能:

SELECT tab.*,
   End(pd) - Begin(pd) AS val
FROM tab
WHERE Cnt > 0
-- create one rows for each group of 5 (days)
EXPAND ON PERIOD(DATE, DATE + Cnt) AS pd BY INTERVAL '5' DAY