基于CTE的SQL去重需求:按Auth_Number去除重复数据
解决按Auth_Number去重的实用方案
嘿,你遇到的这个问题挺常见的——同一个Auth_Number因为fax_date带了时分秒的时间信息,导致导出时出现大量重复的明细记录。要保留每个唯一Auth_Number的完整数据,我给你几个靠谱的解决思路,都是SQL里常用的方法:
方法1:用ROW_NUMBER()窗口函数(最推荐)
这个方法最灵活,既能精准控制保留哪一条记录(比如最新的传真记录,或者最早的),还能完整保留所有明细字段。
假设你的三个CTE最终是通过关联得到结果,那可以在最终查询里加一层窗口函数标记:
With Memb AS ( Select Distinct mbc.Hsc_Id AS Auth_Number, mbc.POL_ISS_ST_CD AS Policy_State, mb.fst_nm AS Member_First_Name, mb.lst_nm AS Member_Last_Name, -- 这里替换成你实际的fax_date字段名 your_fax_column AS fax_date From ... -- 你的原始表关联逻辑 ), -- 另外两个CTE的定义... CTE2 AS ( ... ), CTE3 AS ( ... ) -- 核心逻辑:给每个Auth_Number分组标记序号 SELECT * FROM ( SELECT *, -- 按Auth_Number分组,每组内按fax_date降序排(最新的排第一) ROW_NUMBER() OVER (PARTITION BY Auth_Number ORDER BY fax_date DESC) AS record_rank FROM Memb JOIN CTE2 ON ... -- 替换成你的关联条件 JOIN CTE3 ON ... ) AS ranked_records WHERE record_rank = 1; -- 只留每组的第一条记录,实现去重
关键细节:
PARTITION BY Auth_Number:把数据按Auth_Number拆成一个个独立的组ORDER BY fax_date DESC:控制组内记录的顺序,DESC是取最新的那条,要是想保留最早的改成ASC就行- 外层的
WHERE record_rank = 1:过滤掉重复项,只留每个Auth_Number对应的目标记录
方法2:截断fax_date的时间部分后用DISTINCT
如果fax_date的时分秒对你来说完全没用,那可以先把它转成纯日期格式,再用DISTINCT去重:
With Memb AS ( Select Distinct mbc.Hsc_Id AS Auth_Number, mbc.POL_ISS_ST_CD AS Policy_State, mb.fst_nm AS Member_First_Name, mb.lst_nm AS Member_Last_Name, -- 截断时间,只保留日期部分(不同SQL语法可能略有不同,比如SQL Server用CAST,MySQL用DATE()) CAST(your_fax_column AS DATE) AS fax_date From ... ), -- 另外两个CTE定义... CTE2 AS ( ... ), CTE3 AS ( ... ) SELECT DISTINCT * FROM Memb JOIN CTE2 ON ... JOIN CTE3 ON ...;
注意:
这个方法只适合你不需要时间部分的场景,要是必须保留fax_date的完整时间戳,还是用方法1更合适。
方法3:GROUP BY聚合(适合字段少的情况)
如果你的明细字段不多,而且大部分字段可以用聚合函数处理(比如取最大、最小值),也可以用GROUP BY:
With Memb AS ( Select mbc.Hsc_Id AS Auth_Number, mbc.POL_ISS_ST_CD AS Policy_State, mb.fst_nm AS Member_First_Name, mb.lst_nm AS Member_Last_Name, your_fax_column AS fax_date From ... ), -- 另外两个CTE定义... CTE2 AS ( ... ), CTE3 AS ( ... ) SELECT Auth_Number, Policy_State, Member_First_Name, Member_Last_Name, MAX(fax_date) AS latest_fax_date -- 取该Auth_Number对应的最新传真时间 -- 其他字段如果是唯一的,直接列出来;如果有重复,选合适的聚合函数(比如MIN、MAX) FROM Memb JOIN CTE2 ON ... JOIN CTE3 ON ... GROUP BY Auth_Number, Policy_State, Member_First_Name, Member_Last_Name;
缺点:
如果明细字段很多,GROUP BY的子句会特别长,而且对于字符串类型的字段,聚合函数的选择很受限,所以一般优先用方法1。
内容的提问来源于stack exchange,提问作者cardonas
相关产品推荐
相关产品推荐

