TSQL:根据最大值(日期)删除重复项

TSQL:根据最大值(日期)删除重复项,tsql,sql-server-2000,Tsql,Sql Server 2000,我正在搜索一个查询,以选择最长日期(一个datetime列),并保留其id和row\u id。需要删除源表中的行 源数据 id date row_id(unique) 1 11/11/2009 1 1 12/11/2009 2 1 13/11/2009 3 2 1/11/2009 4 预期幸存者 1 13/11/2009 3 2 1/11/2009 4 我需要什么查询才

我正在搜索一个查询,以选择最长日期(一个
datetime
列),并保留其
id
row\u id
。需要删除源表中的行

源数据

id     date         row_id(unique)
1      11/11/2009    1
1      12/11/2009    2
1      13/11/2009    3
2      1/11/2009     4
预期幸存者

1      13/11/2009    3
2      1/11/2009     4
我需要什么查询才能获得我想要的结果?

在PostgreSQL上测试:

delete from table where (id, date) not in (select id, max(date) from table group by id);
在PostgreSQL上测试:

delete from table where (id, date) not in (select id, max(date) from table group by id);

有多种方法可以做到这一点,但基本思想是相同的:
-标识要保留的行
-将表中的每一行与要保留的行进行比较
-删除任何不匹配的内容





有多种方法可以做到这一点,但基本思想是相同的:
-标识要保留的行
-将表中的每一行与要保留的行进行比较
-删除任何不匹配的内容





因为您使用的是SQLServer2000,所以无法使用设置序列的行覆盖技术,也无法为每个唯一id标识最上面的行

因此,您建议的技术是使用datetime列获取前1行以删除重复项。这可能行得通,但仍有可能得到具有相同datetime值的副本。但这很容易检查

首先检查基于id和日期列的所有行都是唯一的假设:

CREATE TABLE #TestTable (rowid INT IDENTITY(1,1), thisid INT, thisdate DATETIME)
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '11/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '12/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '12/12/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (2, '1/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (2, '1/11/2009')

SELECT COUNT(*) AS thiscount
FROM #TestTable
GROUP BY thisid, thisdate
HAVING COUNT(*) > 1
此示例返回的值为2-表示即使在使用“日期”列删除重复项之后,仍然会得到重复项。如果您返回0,那么您已经证明了所建议的技术可以工作

在对生产数据进行重复数据消除时,我认为应该采取一些预防措施,并在前后进行测试。您应该创建一个表来保存计划删除的行,以便在执行delete语句后,如果需要,可以轻松地恢复它们

另外,最好事先知道要删除多少行,以便在删除前后验证计数,并测量删除操作的大小。根据受影响的行数,您可以计划何时运行该操作

要在重复数据消除过程之前进行测试,请查找出现的情况

-- Get occurrences of duplicates
SELECT COUNT(*) AS thiscount
FROM 
#TestTable
GROUP BY thisid
HAVING COUNT(*) > 1
ORDER BY thisid
这将为您提供具有多个相同id行的行。将此查询中的行捕获到临时表中,然后使用总和运行查询,以根据您的键获取不唯一的行总数


要获取计划删除的行数,需要基于唯一键的重复行数,以及基于唯一键的不同行数。从出现次数中减去不同的行。所有这些都非常简单-所以我将留给您去做。

因为您使用的是SQL Server 2000,所以您无法使用设置序列的逐行扫描技术,也无法为每个唯一id标识最上面的一行

因此,您建议的技术是使用datetime列获取前1行以删除重复项。这可能行得通,但仍有可能得到具有相同datetime值的副本。但这很容易检查

首先检查基于id和日期列的所有行都是唯一的假设:

CREATE TABLE #TestTable (rowid INT IDENTITY(1,1), thisid INT, thisdate DATETIME)
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '11/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '12/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (1, '12/12/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (2, '1/11/2009')
INSERT INTO #TestTable (thisid,thisdate) VALUES  (2, '1/11/2009')

SELECT COUNT(*) AS thiscount
FROM #TestTable
GROUP BY thisid, thisdate
HAVING COUNT(*) > 1
此示例返回的值为2-表示即使在使用“日期”列删除重复项之后,仍然会得到重复项。如果您返回0,那么您已经证明了所建议的技术可以工作

在对生产数据进行重复数据消除时,我认为应该采取一些预防措施,并在前后进行测试。您应该创建一个表来保存计划删除的行,以便在执行delete语句后,如果需要,可以轻松地恢复它们

另外,最好事先知道要删除多少行,以便在删除前后验证计数,并测量删除操作的大小。根据受影响的行数,您可以计划何时运行该操作

要在重复数据消除过程之前进行测试,请查找出现的情况

-- Get occurrences of duplicates
SELECT COUNT(*) AS thiscount
FROM 
#TestTable
GROUP BY thisid
HAVING COUNT(*) > 1
ORDER BY thisid
这将为您提供具有多个相同id行的行。将此查询中的行捕获到临时表中,然后使用总和运行查询,以根据您的键获取不唯一的行总数

要获取计划删除的行数,需要基于唯一键的重复行数,以及基于唯一键的不同行数。从出现次数中减去不同的行。所有这些都很简单,所以我就让你去做吧。

试试这个

declare @t table (id int, dt DATETIME,rowid INT IDENTITY(1,1))
INSERT INTO @t (id,dt) VALUES  (1, '11/11/2009')
INSERT INTO @t (id,dt) VALUES  (1, '11/12/2009')
INSERT INTO @t (id,dt) VALUES  (1, '11/13/2009')
INSERT INTO @t (id,dt) VALUES  (2, '11/01/2009')
查询:

delete from @t where rowid not in(
select t.rowid from @t t
inner join(
select MAX(dt)maxdate
from @t
group by id) X
on t.dt = X.maxdate )

select * from @t
输出:

id dt rowid
1 2009-11-13 00:00:00.000 3
2 2009-11-01 00:00:00.000 4
试试这个

declare @t table (id int, dt DATETIME,rowid INT IDENTITY(1,1))
INSERT INTO @t (id,dt) VALUES  (1, '11/11/2009')
INSERT INTO @t (id,dt) VALUES  (1, '11/12/2009')
INSERT INTO @t (id,dt) VALUES  (1, '11/13/2009')
INSERT INTO @t (id,dt) VALUES  (2, '11/01/2009')
查询:

delete from @t where rowid not in(
select t.rowid from @t t
inner join(
select MAX(dt)maxdate
from @t
group by id) X
on t.dt = X.maxdate )

select * from @t
输出:

id dt rowid
1 2009-11-13 00:00:00.000 3
2 2009-11-01 00:00:00.000 4
我已经验证了这个答案

INSERT INTO #t (id,dt) VALUES  (1, '11/11/2009')
INSERT INTO #t (id,dt) VALUES  (1, '11/12/2009')
INSERT INTO #t (id,dt) VALUES  (1, '11/13/2009')
INSERT INTO #t (id,dt) VALUES  (2, '11/01/2009')
select * from #t

;WITH T AS(
select dense_rank() over(partition by id order by dt desc)NO,DT,ID,rowid  from #t )

DELETE T  WHERE NO>1

我已经测试了这个答案。

你说删除重复项,但显然你正在删除最小值和最大值之间的所有日期-你能澄清一下吗?你说删除重复项,但是显然您正在删除最小值和最大值之间的所有日期-您能澄清一下吗?公用表表达式在SQL Server 2000中不起作用公用表表达式在SQL Server 2000中不起作用
INSERT INTO #t (id,dt) VALUES  (1, '11/11/2009')
INSERT INTO #t (id,dt) VALUES  (1, '11/12/2009')
INSERT INTO #t (id,dt) VALUES  (1, '11/13/2009')
INSERT INTO #t (id,dt) VALUES  (2, '11/01/2009')
select * from #t

;WITH T AS(
select dense_rank() over(partition by id order by dt desc)NO,DT,ID,rowid  from #t )

DELETE T  WHERE NO>1