复制上一行的行数据

时间:2015-10-30 20:44:22

标签: sql sql-server tsql

我有一张如下表:

╔══════════════════════════════════════╦═══════════════════════╗
║                  Id                  ║ ContiguousSubnetStart ║
╠══════════════════════════════════════╬═══════════════════════╣
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.8            ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 1                     ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 1                     ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 1                     ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 1                     ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 1                     ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 10.60.88.28           ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 1                     ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 1                     ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 1                     ║
╚══════════════════════════════════════╩═══════════════════════╝

我希望此表转换为:

╔══════════════════════════════════════╦═══════════════════════╗
║                  Id                  ║ ContiguousSubnetStart ║
╠══════════════════════════════════════╬═══════════════════════╣
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.8            ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.8            ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ 53DC370E-8C7D-4526-9292-35125443E4B1 ║ 10.60.66.18           ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 10.60.88.28           ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 10.60.88.28           ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 10.60.88.28           ║
║ B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 ║ 10.60.88.28           ║
╚══════════════════════════════════════╩═══════════════════════╝

不使用游标。 ip-address后跟1代表一组。

2 个答案:

答案 0 :(得分:6)

此类操作需要一些列,您可以在其中订购行以获得所需的结果。在示例中,我使用窗口函数rn

手动添加了这样的列row_number
DECLARE @t TABLE
    (
      Id UNIQUEIDENTIFIER ,
      ContiguousSubnetStart VARCHAR(100)
    )

INSERT  INTO @t
VALUES  ( '53DC370E-8C7D-4526-9292-35125443E4B1', '10.60.66.8' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '10.60.66.18' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
        ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
        ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '10.60.88.28' ),
        ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' ),
        ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' ),
        ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' )


;WITH cte AS(SELECT *, ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) rn FROM @t)
SELECT oa.Id, oa.ContiguousSubnetStart 
FROM cte t1
OUTER APPLY(SELECT TOP 1 * 
            FROM cte t2 
            WHERE t1.Id = t2.Id AND t2.ContiguousSubnetStart <> '1' AND t2.rn <= t1.rn 
            ORDER BY rn DESC)oa

如果您从cte中选择,您会看到:

Id                                      ContiguousSubnetStart   rn
53DC370E-8C7D-4526-9292-35125443E4B1    10.60.66.8              1
53DC370E-8C7D-4526-9292-35125443E4B1    1                       2
53DC370E-8C7D-4526-9292-35125443E4B1    10.60.66.18             3
53DC370E-8C7D-4526-9292-35125443E4B1    1                       4
53DC370E-8C7D-4526-9292-35125443E4B1    1                       5
53DC370E-8C7D-4526-9292-35125443E4B1    1                       6
53DC370E-8C7D-4526-9292-35125443E4B1    1                       7
B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7    10.60.88.28             8
B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7    1                       9
B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7    1                       10
B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7    1                       11

如果您有一个像增量标识或日期列这样的列,您可以使用该列明确地对表中的数据进行排序,只需使用该列而不是rn,您就不再需要cte了。假设列名为SomeOrderingColumn,那么您的语句将如下所示:

SELECT oa.Id, oa.ContiguousSubnetStart 
FROM TableName t1
OUTER APPLY(SELECT TOP 1 * 
            FROM TableName t2 
            WHERE t1.Id = t2.Id AND t2.ContiguousSubnetStart <> '1' 
                  AND t2.SomeOrderingColumn <= t1.SomeOrderingColumn
            ORDER BY SomeOrderingColumn DESC)oa

如果没有该排序列,您仍然可以获得所需的结果,但在任何情况下都不会保证,并且您可能会在某一天遇到错误的结果。这已被多次讨论过,您可以发现只有在明确使用ORDER BY子句时才能保证只获得有序结果。但您无法使用guidip列来订购数据。因此,您必须在表格中再添加一列,以保证排序,例如递增IDDateTime列。

答案 1 :(得分:0)

您还可以使用行计数执行WHILE循环,不确定哪种环境对您的环境有更好的性能。

CREATE TABLE #Test
(
  Id UNIQUEIDENTIFIER ,
  ContiguousSubnetStart VARCHAR(100)
)

INSERT  INTO #Test
VALUES  ( '53DC370E-8C7D-4526-9292-35125443E4B1', '10.60.66.8' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '10.60.66.18' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
    ( '53DC370E-8C7D-4526-9292-35125443E4B1', '1' ),
    ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '10.60.88.28' ),
    ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' ),
    ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' ),
    ( 'B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7', '1' )

SELECT *, [RN] = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) INTO #NewTable FROM #Test

DECLARE @Count INT = (SELECT MAX(RN) FROM #NewTable)
DECLARE @CurrentRow INT = 1

WHILE @Count > 0
BEGIN
    UPDATE #NewTable
    SET ContiguousSubnetStart = (SELECT ContiguousSubnetStart FROM #NewTable WHERE RN = @CurrentRow - 1)
    WHERE ContiguousSubnetStart = '1'
    AND RN = @CurrentRow

    SET @CurrentRow = @CurrentRow + 1
    SET @Count = @Count - 1
END

结果集:

===========================================================
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.8  | 1  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.8  | 2  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.18 | 3  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.18 | 4  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.18 | 5  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.18 | 6  |
| 53DC370E-8C7D-4526-9292-35125443E4B1 | 10.60.66.18 | 7  |
| B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 | 10.60.88.28 | 8  |
| B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 | 10.60.88.28 | 9  |
| B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 | 10.60.88.28 | 10 |
| B6F8484C-B8F9-4CB0-B6BF-395A7599FFB7 | 10.60.88.28 | 11 |
===========================================================