【问题标题】:SQL select a row X times and insert into newSQL选择行X次并插入新的
【发布时间】:2019-06-20 15:34:34
【问题描述】:

我正在尝试将一堆数据从旧数据库迁移到新数据库,旧数据库过去只有单行上发生的警报数量。新数据库为每个发生的警报插入一条新记录。这是它的外观的基本版本。我想从表 1 中选择每一行,并将警报值的数量作为新行插入到表 2 中。

表一:

|  Alarm ID    |  Alarm Value   |
|--------------|----------------|
|     1        |        3       |
|     2        |        2       |

应按以下值进入报警表。

表 2:

| Alarm New ID |  Value   |
|--------------|----------|
|     1        |    1     |
|     2        |    1     |
|     3        |    1     |
|     4        |    2     |
|     5        |    2     |

我想创建一个选择插入脚本来执行此操作,因此选择语句将返回出现在“值”列中的行数。

【问题讨论】:

  • 除非我遗漏了什么,否则您的示例数据对我来说根本没有任何意义。
  • 我已更改列名,希望对您有所帮助。
  • 请注意,同时使用Value 列并将实例编号存储为单独的行是有问题的。如果将警报 3 的 Value 更改为 17 会怎样?

标签: sql sql-server


【解决方案1】:

递归 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)

【讨论】:

  • 部分记录超过100条,需要在哪里添加?
  • 注意:您的 SQL 中有错字:(max recursion 0)而不是(maxrecursion 0)
【解决方案2】:

使用 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

【讨论】:

  • 没关系,我重新阅读了您的问题,似乎每个警报的计数都通过它在表格中的出现来跟踪。
【解决方案3】:

您可以使用 Tally 表,而不是使用递归(顾名思义)并且会在 100 行时失败的 rCTE,它往往也快得多:

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;

【讨论】:

  • 这也是一个不错的方法,但是,我猜在设定数量的记录 100,000 之后,计数停止返回结果?在 SQL Server 中,递归限制可以设置为无限制。
猜你喜欢
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
相关资源
最近更新 更多