我正在尝试将一堆数据从一个旧数据库迁移到一个新数据库,旧数据库过去只具有在单行中发生的警报数量。新数据库为发生的每个警报插入一条新记录。这是它外观的基本版本。我想从表1中选择每一行,并将警报值的数目作为新行插入表2中。
表1:
| Alarm ID | Alarm Value |
|--------------|----------------|
| 1 | 3 |
| 2 | 2 |
应作为以下值进入警报表。
表2:
| Alarm New ID | Value |
|--------------|----------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
我想创建一个选择插入脚本来执行此操作,因此select语句将带回出现在“值”列中的行数。
答案 0 :(得分:4)
递归CTE为此很方便:
with cte as (
select id, alarm, 1 as n
from t
union all
select id, alarm, n + 1
from cte
where n < alarm
)
select row_number() over (order by id) as alarm_id, id as value
from cte
order by 1
option (maxrecursion 0);
注意:如果您的值不超过100,则可以删除OPTION (MAXRECURSION 0)
。
答案 1 :(得分:0)
使用CTE复制值。
DECLARE @T TABLE(AlarmID INT, Value INT)
INSERT @T VALUES
(1,3),
(2,2)
;WITH ReplicateAmount AS
(
SELECT AlarmID, Value FROM @T
UNION ALL
SELECT R.AlarmID, Value=(R.Value - 1)
FROM ReplicateAmount R
INNER JOIN @T T ON R.AlarmID = T.AlarmID
WHERE R.Value > 1
)
SELECT
AlarmID = ROW_NUMBER() OVER( ORDER BY AlarmID),
Value = AlarmID --??
FROM
ReplicateAmount
ORDER BY
AlarmID
这回答了您的问题。我认为下面的查询会更有用,但是,您不包括使用情况上下文。
SELECT
AlarmID,
Value
FROM
ReplicateAmount
ORDER BY
AlarmID
答案 2 :(得分:0)
您可以使用Tally表,而不是使用递归的rCTE(顾名思义)并在100行时失败,您可以使用Tally表,该表也往往更快:
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3)
SELECT ROW_NUMBER() OVER (ORDER BY V.AlarmID,T.I) AS AlarmNewID,
V.AlarmID
FROM (VALUES(1,3),(2,2))V(AlarmID,AlarmValue)
JOIN Tally T ON V.AlarmValue >= T.I;