我有一张如下表:
╔══════════════════════════════════════╦═══════════════════════╗
║ 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代表一组。
答案 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
子句时才能保证只获得有序结果。但您无法使用guid
或ip
列来订购数据。因此,您必须在表格中再添加一列,以保证排序,例如递增ID
或DateTime
列。
答案 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 |
===========================================================