我有一个表,列表中有一个日期,唯一的ID是(日期,时间和参考的连接)。加上一个包含数字f项的列。
我希望能够将这些数据分成如下图所示。因此,上面数据中的每一行都会根据列出的项目数进行拆分。对于例如' 142691'有11个项目,所以我想把它分成11个项目,但
正如您所看到的那样,创建了唯一ID,因为某些引用可以有多个条目,例如' 142692'对于每个条目,时间增加一分钟。
如果有人可以提供帮助,我将不胜感激。
我尝试了以下内容:
DECLARE @COUNT INT
SET @count = 0
DECLARE @add TABLE (ID BIGINT, REF INT, DATE INT, PERIOD INT, TIME VARCHAR(12), ITEMS INT)
WHILE (@count < (SELECT DURATION FROM @add))
BEGIN
INSERT INTO @add
SELECT @COUNT
SET @count = (@count + 1)
END
DECLARE @SPLITRW TABLE (ID BIGINT, REF INT, DATE INT, PERIOD INT, TIME VARCHAR(12), ITEMS INT)
INSERT INTO @SPLITRW
(ID, REF, DATE, PERIOD,TIME, ITEMS)
SELECT ID, REF, DATE, PERIOD, (TIME + @COUNT), ITEMS
FROM dbo.dataset
SELECT ID, REF, DATE, PERIOD, TIME , items
FROM @SPLITRW SR
INNER JOIN @add AD
ON AD.ID BETWEEN 1 AND AD.items
答案 0 :(得分:3)
如果您没有数字或计数表,则可以使用临时计数表。
示例强>
Select A.ID
,A.Ref
,A.Date
,A.Period
,Time=dateadd(MINUTE,N,A.Time)
,A.Items
From YourTable A
Join ( Select Top 1000 N=Row_Number() Over (Order By (Select NULL))-1
From master..spt_values n1, master..spt_values n2
) B on B.N<=A.Items
您可能会注意到子查询中的**Select TOP 1000**
。您可以将其调整为更合理/最大的数字。或者你可以
...
Join ( Select Top (Select 1+max(Items) from YourTable) N=Row_Number() Over (Order By (Select NULL))-1
From master..spt_values n1, master..spt_values n2
) B on B.N<=A.Items
编辑 - 按要求
使用spt_values的子查询(可以是任何适当大小的表)只需生成一个从0到9999的临时计数表。然后我们只需将数据加入ITEMS的限制即可创建1-many。我们还使用N来增加你的TIME。
答案 1 :(得分:3)
我相信这会回答你的问题。
我从名为Multiplier的递归CTE开始,它为每个ID
保留等于ITEMS
值+1的行。 RN
(行数)值从0开始并递增到ITEMS
。如果您怀疑的行数太多,请将WHERE RN < ITEMS
更改为WHERE RN < ITEMS-1
。
样本CTE数据:
ID ITEMS RN
20180403165100142691 11 0
20180403165100142691 11 1
20180403165100142691 11 2
20180403165100142691 11 3
20180403165100142691 11 4
20180403165100142691 11 5
20180403165100142691 11 6
20180403165100142691 11 7
20180403165100142691 11 8
20180403165100142691 11 9
20180403165100142691 11 10
20180403165100142691 11 11
从那里,我们JOIN
将CTE返回到ID
上的主表,并对日期/时间字段进行一些操作,每行增加1分钟(添加RN
})。
DECLARE @Test TABLE (ID VARCHAR(100), REF INT, [DATE] VARCHAR(10), [PERIOD] INT, [TIME] TIME, NUM INT, ITEMS INT)
INSERT INTO @Test
VALUES ('20180403165100142691',142691,'20180403',37,'16:51',NULL,11)
,('20180403165500142692',142692,'20180403',37,'16:55',NULL,15)
,('20180403171000142692',142692,'20180403',37,'17:15',NULL,8)
,('20180403170700142693',142693,'20180403',37,'17:07',NULL,20)
,('20180403235700142693',142693,'20180403',37,'23:57',NULL,7)
;WITH Multiplier AS
(
SELECT ID, ITEMS, 0 AS RN
FROM @Test
UNION ALL
SELECT ID, ITEMS, RN+1
FROM Multiplier
WHERE RN < ITEMS
)
SELECT T.ID,
T.REF,
CONVERT(VARCHAR(10),DATEADD(MINUTE,RN,CONVERT(DATETIME,T.[DATE])+CONVERT(DATETIME,T.[TIME])),112) AS [DATE],
T.[PERIOD],
CONVERT(VARCHAR(5),DATEADD(MINUTE,RN,T.[TIME]),108) AS [TIME],
T.NUM,
T.ITEMS
FROM @Test T
JOIN Multiplier I ON T.ID=I.ID
ORDER BY T.ID, T.[TIME]