如何删除表中重复数据,仅保留需要的一条

文章讲述了如何在数据库表中检测并删除重复的学生成绩数据。通过使用窗口函数ROW_NUMBER()和DENSE_RANK(),结合PARTITIONBY和ORDERBY子句,可以有效地删除重复行,比如保留每个学生最新月份的成绩或特定月份的数据。此外,还提到了在存在相同月份数据时,使用DENSE_RANK()的必要性。
摘要由CSDN通过智能技术生成

假设有学生成绩表如下:

NAMEMONTH_TIMEKEYCHINESEMATHSENGLISHPHYSICSCHEMISTRYBIOLOGY
张三2023M01726267658971
张三2023M02807083797697
张三2023M03689063947093
张三2023M04868695726972
张三2023M05739699839582
张三2023M05739699839582
李四2023M02866170619090
李四2023M03749373908466
李四2023M04998961867386
李四2023M05889477996679
李四2023M06686385656675
李四2023M06686385656675
王五2023M03699464956796
王五2023M04916194839174
王五2023M05667482747797
王五2023M06968482878370
王五2023M07988178916976
王五2023M07988178916976
赵六2023M01959193746964
赵六2023M02906477946395
赵六2023M03669566618091
赵六2023M04966776828775
赵六2023M05926195987997
赵六2023M05926195987997

先看看表中有没有重复数据,相同姓名和月份的数据视为重复数据

SELECT * FROM (
	SELECT A.*
	,COUNT(1) OVER (PARTITION BY A.NAME,MONTH_TIMEKEY) CNT
	FROM TEST_TAB_SCORE A
) B WHERE B.CNT>1 

输出:

NAMEMONTH_TIMEKEYCHINESEMATHSENGLISHPHYSICSCHEMISTRYBIOLOGYCNT
张三2023M057396998395822
张三2023M057396998395822
李四2023M066863856566752
李四2023M066863856566752
王五2023M079881789169762
王五2023M079881789169762
赵六2023M059261959879972
赵六2023M059261959879972

可见,表中包含重复数据。

那如何删除这些重复数据呢?使用distinct可以去除重复数据取出来,但无法删除原表中重复数据。

由于表中每一列具有维一值ROWID,即使重复数据的ROWID也不相同,因此,可以通过删除ROWID来删除指定行

--保留最新进入表的一行,即ROWID较大的一行
DELETE FROM TEST_TAB_SCORE A
WHERE EXISTS(
	SELECT 1 FROM (
		SELECT A.*
		,ROW_NUMBER() OVER (PARTITION BY A.NAME,MONTH_TIMEKEY ORDER BY ROWID DESC) RN 
		,ROWID ROW_ID
		FROM TEST_TAB_SCORE A
	) B WHERE A.ROWID = B.ROW_ID AND B.RN>1 
)

删除后数据如下:

NAMEMONTH_TIMEKEYCHINESEMATHSENGLISHPHYSICSCHEMISTRYBIOLOGY
张三2023M01726267658971
张三2023M02807083797697
张三2023M03689063947093
张三2023M04868695726972
张三2023M05739699839582
李四2023M02866170619090
李四2023M03749373908466
李四2023M04998961867386
李四2023M05889477996679
李四2023M06686385656675
王五2023M03699464956796
王五2023M04916194839174
王五2023M05667482747797
王五2023M06968482878370
王五2023M07988178916976
赵六2023M01959193746964
赵六2023M02906477946395
赵六2023M03669566618091
赵六2023M04966776828775
赵六2023M05926195987997

可见重复行已删除。

如果我们每个姓名只想保留最新的一个月的数据,那相同姓名的数据即视为重复数据,也可以用上述方法进行删除,只需改变窗口函数的分组和排序条件即可。

--保留每个姓名最新一个月的数据
DELETE FROM TEST_TAB_SCORE A
WHERE EXISTS(
	SELECT 1 FROM (
		SELECT A.*
		,ROW_NUMBER() OVER (PARTITION BY A.NAME ORDER BY MONTH_TIMEKEY DESC) RN 
		,ROWID ROW_ID
		FROM TEST_TAB_SCORE A
	) B WHERE A.ROWID = B.ROW_ID AND B.RN>1 
)

删除后数据如下:

NAMEMONTH_TIMEKEYCHINESEMATHSENGLISHPHYSICSCHEMISTRYBIOLOGY
张三2023M05739699839582
李四2023M06686385656675
王五2023M07988178916976
赵六2023M05926195987997

此方法也可用于保留指定条件数据的去重,例如保留倒数第三个月的数据,这里改用DENSE_RANK是因为,如果月份有数据重复(如本文最开始的表格),用ROW_NUMBER会得到错误结果

--保留倒数第三个月的数据
DELETE FROM TEST_TAB_SCORE A
WHERE EXISTS(
	SELECT 1 FROM (
		SELECT A.*
		,DENSE_RANK() OVER (PARTITION BY A.NAME ORDER BY MONTH_TIMEKEY DESC) RN 
		,ROWID ROW_ID
		FROM TEST_TAB_SCORE A
	) B WHERE A.ROWID = B.ROW_ID AND B.RN<>3 
)

删除后数据如下:

NAMEMONTH_TIMEKEYCHINESEMATHSENGLISHPHYSICSCHEMISTRYBIOLOGY
张三2023M03689063947093
李四2023M04998961867386
王五2023M05667482747797
赵六2023M03669566618091

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值