ruo*_*ola 5 sql t-sql sql-server duplicates sql-delete
我对表具有以下结构DataTable:每列都是数据类型int,RowID是标识列和主键。LinkID是外键,并链接到另一个表的行。
RowID LinkID Order Data DataSpecifier
1 120 1 1 1
2 120 2 1 3
3 120 3 1 10
4 120 4 1 13
5 120 5 1 10
6 120 6 1 13
7 371 1 6 2
8 371 2 3 5
9 371 3 8 1
10 371 4 10 1
11 371 5 7 2
12 371 6 3 3
13 371 7 7 2
14 371 8 17 4
.................................
.................................
Run Code Online (Sandbox Code Playgroud)
我正在尝试执行一个查询,该查询LinkID以以下方式更改每个批次:
LinkID(例如,第一批是这里的前6行)Order列排序Data和DataSpecifier列视为一个比较单位(可以将它们视为一列,称为dataunit):
Order1开始保留尽可能多的行,直到dataunit通过LinkID所以对于LinkID 120:
Order=1在这里),只要没有发现重复即可。Order = 5(dataunit 1 10已经看到)。LinkID=120 AND Order>=5经过类似的过程LinkID 371(以及LinkID表中的其他所有过程),处理后的表将如下所示:
RowID LinkID Order Data DataSpecifier
1 120 1 1 1
2 120 2 1 3
3 120 3 1 10
4 120 4 1 13
7 371 1 6 2
8 371 2 3 5
9 371 3 8 1
10 371 4 10 1
11 371 5 7 2
12 371 6 3 3
.................................
.................................
Run Code Online (Sandbox Code Playgroud)
我已经做了很多SQL查询,但是从来没有这么复杂。我知道我需要使用类似以下的查询:
DELETE FROM DataTable
WHERE RowID IN (SELECT RowID
FROM DataTable
WHERE -- ?
GROUP BY LinkID
HAVING COUNT(*) > 1 -- ?
ORDER BY [Order]);
Run Code Online (Sandbox Code Playgroud)
但是我似乎无法解决这个问题并获得正确的查询。我最好用一个可执行(可重用)查询在纯SQL中执行此操作。
您可以使用ROW_NUMBER()窗口函数来识别原始行之后的任何行。之后,您可以删除与行号LinkID大于或等于任何遇到的行匹配且大于或Order等于行号大于 1 的行。
(我最初使用第二个 CTE 来获取MIN order,但我意识到只要连接order大于等于orderDataUnitId 的第二个实例,就没有必要。通过删除MIN查询计划变得相当简单简单高效。)
WITH DataUnitInstances AS (
SELECT *
, ROW_NUMBER() OVER
(PARTITION BY LinkID, [Data], [DataSpecifier] ORDER BY [Order]) DataUnitInstanceId
FROM DataTable
)
DELETE FROM DataTable
FROM DataTable dt
INNER JOIN DataUnitInstances dup ON dup.LinkID = dt.LinkID
AND dup.[Order] <= dt.[Order]
AND dup.DataUnitInstanceId > 1
Run Code Online (Sandbox Code Playgroud)
以下是示例数据的输出,与您期望的结果相匹配:
+-------+--------+-------+------+---------------+
| RowID | LinkID | Order | Data | DataSpecifier |
+-------+--------+-------+------+---------------+
| 1 | 120 | 1 | 1 | 1 |
| 2 | 120 | 2 | 1 | 3 |
| 3 | 120 | 3 | 1 | 10 |
| 4 | 120 | 4 | 1 | 13 |
| 7 | 371 | 1 | 6 | 2 |
| 8 | 371 | 2 | 3 | 5 |
| 9 | 371 | 3 | 8 | 1 |
| 10 | 371 | 4 | 10 | 1 |
| 11 | 371 | 5 | 7 | 2 |
| 12 | 371 | 6 | 3 | 3 |
+-------+--------+-------+------+---------------+
Run Code Online (Sandbox Code Playgroud)