基于 SQL 的仅根据标准删除表中的重复项

3

假设我有一个包含列的表:

CustomerNumber
Lastname
Firstname
PurchaseDate

...以及其他在此处未显示不会改变问题的列。

在此表中,我可以为同一客户拥有许多具有不同购买日期的行(我知道,设计很差...我只想解决报告问题,而不是真的试图解决问题的根源)。

如何在SQL中保留每个客户的一条记录,并删除其余记录的最新日期?对于我的情况,group by似乎不起作用。


2
这个表的主键是什么? - procrastinate_later
这不是前端应用程序使用的真正表格...它有点像日志 - 没有主键。 - user1327073
1
您是想要实际删除还是只选择具有最大购买日期的记录? - Tim Lehner
3个回答

7
;with a as
(
select row_number() over (partition by CustomerNumber, Lastname, Firstname order by PurchaseDate desc) rn
from <table>
)
delete from a where rn > 1

打败我了,我正准备发布一个像这样的CTE版本。 - Taryn
这很不错。你的版本中一个好的特点是,即使最新购买日期有多行记录,它也只会选择一条记录。 - Chris Smith

3

这对我有用(在DB2上):

 DELETE FROM my_table 
 WHERE (CustomerNumber, Lastname, Firstname, PurchaseDate) 
 NOT IN ( 
       SELECT CustomerNumber, Lastname, Firstname, MAX(PurchaseDate) 
       FROM my_table 
       GROUP BY CustomerNumber, Lastname, FirstName 
 )

这是一个狐狸表格,并且经过一些修改后也有效了。非常感谢。 - user1327073
很高兴能帮上忙。我不确定这是否为ANSI SQL,因为NOT IN之前的部分不是标量值。你需要修改什么? - procrastinate_later

1
SELECT CustomerNumber, Lastname, Firstname, MAX(PurchaseDate) LatestPurchaseDate
FROM Table
GROUP BY CustomerNumber, Lastname, Firstname

MAX函数将选择最高(最新)日期,并为每个GROUP BY列的唯一组合显示该日期。

编辑:我误解了您想要删除除最新购买日期之外的所有记录。

WITH Keep AS
(
    SELECT CustomerNumber, Lastname, Firstname, MAX(PurchaseDate) LatestPurchaseDate
    FROM Table
    GROUP BY CustomerNumber, Lastname, Firstname
)
DELETE FROM Table
WHERE NOT EXISTS
(
    SELECT *
    FROM Keep
    WHERE Table.CustomerNumber = Keep.CustomerNumber
    AND Table.Lastname = Keep.Lastname
    AND Table.Firstname = Keep.Firstname
    AND Table.PurchaseDate = Keep.LastPurchaseDate
)

我认为你错过了“并删除其余部分?” - LittleBobbyTables - Au Revoir
尝试一下;只要顾客的所有出现次数具有相同的(CustomerNumber,Lastname,Firstname),每个顾客将仅有一行。 - Chris Smith
我知道它会选择正确的记录并排除其余的记录,但是我当时把“删除”的请求理解为实际的“DELETE”语句。 - LittleBobbyTables - Au Revoir
好的,我误解了。已编辑添加DELETE语句。 - Chris Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,