我正在搜索删除表格上的重复条目,我看到了如下例子:
CREATE TABLE Suppliers
(
Id int identity (1,1),
CompanyTitle nvarchar(1000),
ContactName nvarchar(100),
LastContactDate datetime
)
INSERT Suppliers VALUES (N'Melody Music Instruments',N'James Manning', '20090623 10:15')
INSERT Suppliers VALUES (N'Blue Jazz',N'Mike Clark', '20090720 15:40')
INSERT Suppliers VALUES (N'Top Music',N'Katy Swan', '20090827 18:00')
INSERT Suppliers VALUES (N'Blue Jazz',N'Mike Clark', '20090806 10:00')
INSERT Suppliers VALUES (N'Melody Music Instruments',N'James Brown', '20080121 11:20')
INSERT Suppliers VALUES (N'Top Music',N'Katy Perry', '20090825 14:00')
INSERT Suppliers VALUES (N'Top Music',N'Katy Perry', '20090825 14:00')
WITH Duplicate AS
(
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY CompanyTitle ORDER BY LastContactDate DESC)
FROM Suppliers
)
delete from Duplicate where RN > 1
CTE返回类似的东西然后如果值大于1则删除。
RN
--
1
2
1
2
1
2
3
我不明白的是它如何理解将删除哪个条目。它只是通过此示例返回dublicate条目计数。
答案 0 :(得分:4)
您的示例表是一个堆(意味着它没有聚集索引)。
如果查看示例的执行计划,您将看到Bmk1000
位于叶级表扫描的输出列列表中,并且此列将在计划中的所有运算符中传递,直到DELETE
运算符。
Bmk1000
是唯一标识行所在位置的书签(堆的行标识符包含行的文件:Page:Slot的位置),因此{{1}可以使用它}运算符以找到所需的行。
如果您的表具有聚簇索引,您可能会看到聚集索引键列以这种方式传递而不是书签。
答案 1 :(得分:1)
你的问题是什么?它正在删除行号大于1的任何内容。 。 。代码非常明确RN > 1
。
它将行号分配给行,从每个CompanyTitle开始。具有最近联系日期的行的值为1.
因此,此代码正在删除比每个CompanyTitle的最新联系人更旧的所有内容。
答案 2 :(得分:1)
PARTITION BY和ORDER BY子句控制将删除哪些行。如果你稍微扩展CTE,这是如何工作的更明显。 (PostgreSQL语法)
WITH Duplicate AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY CompanyTitle ORDER BY LastContactDate DESC),
CompanyTitle,
LastContactDate
FROM Suppliers
)
select *
from Duplicate
(为了便于阅读,下面添加了空行。)
1 Blue Jazz 2009-08-06 10:00:00
2 Blue Jazz 2009-07-20 15:40:00
1 Melody Music Instruments 2009-06-23 10:15:00
2 Melody Music Instruments 2008-01-21 11:20:00
1 Top Music 2009-08-27 18:00:00
2 Top Music 2009-08-25 14:00:00
3 Top Music 2009-08-25 14:00:00
PARTITION子句将相同的CompanyTitle值保持在一起。 ORDER BY子句通过LastContactDate对CompanyTitle的相同值的行进行排序。由于它按降序排序,因此每个CompanyTitle的最新行将始终为1。
因此,要删除除每个CompanyTitle的最新行之外的所有行,您将删除行号大于1的所有行。