公司客户表去重逻辑及SQL查询实现求助
解决方案:区分重复场景处理company_clients表数据
首先明确:我们定义重复记录为client_id(或其他客户唯一标识字段)相同的记录,以此为基准区分两种场景。以下提供两种可行的SQL实现思路:
思路一:用窗口函数+统计标记一次性处理
WITH client_country_check AS ( -- 统计每个客户的非空去重国家数量,用来区分场景 SELECT client_id, COUNT(DISTINCT CASE WHEN country IS NOT NULL THEN country END) AS unique_country_count FROM company_clients GROUP BY client_id ), ranked_records AS ( -- 给同客户、同国家(空值统一标记)的记录排名,方便取最优记录 SELECT c.*, ROW_NUMBER() OVER ( PARTITION BY client_id, COALESCE(country, 'PLACEHOLDER') ORDER BY -- 优先保留非空国家的记录,再按最后修改时间取最新的 CASE WHEN country IS NOT NULL THEN 0 ELSE 1 END, update_time DESC ) AS record_rank FROM company_clients c JOIN client_country_check cc ON c.client_id = cc.client_id ) SELECT client_id, company_name, -- 场景1:统一取非空国家;场景2:保留原国家 CASE WHEN cc.unique_country_count <= 1 THEN MAX(country) OVER (PARTITION BY client_id) ELSE country END AS country, group_id, other_fields FROM ranked_records rr JOIN client_country_check cc ON rr.client_id = cc.client_id WHERE -- 场景1只保留同国家分组的第一条;场景2保留所有记录 (cc.unique_country_count <= 1 AND rr.record_rank = 1) OR (cc.unique_country_count > 1)
逻辑说明
client_country_check:统计每个客户的非空去重国家数——数量≤1对应场景1(同地点/空地点重复),>1对应场景2(多国家合法重复)。ranked_records:给同客户、同国家(空值用占位符统一)的记录排名,确保能拿到最优的那条(比如非空、最新的)。- 最终筛选:场景1合并为单条,场景2保留所有不同国家的记录。
思路二:拆分场景分别处理(更直观)
如果需要对不同场景的字段做不同聚合处理,用UNION ALL拆分更清晰:
-- 场景1:同地点/空地点重复,合并为单条 WITH client_country_check AS ( SELECT client_id, COUNT(DISTINCT CASE WHEN country IS NOT NULL THEN country END) AS unique_country_count FROM company_clients GROUP BY client_id ) SELECT client_id, MAX(company_name) AS company_name, -- 假设同客户的公司名一致,不一致可按需调整 COALESCE(MAX(country), MIN(country)) AS country, -- 取非空的国家,无则保留空 STRING_AGG(DISTINCT group_id, ', ') AS merged_group_ids, -- 合并所有分组(MySQL用GROUP_CONCAT) MAX(other_fields) AS latest_other_fields -- 取最新的其他字段值 FROM company_clients c JOIN client_country_check cc ON c.client_id = cc.client_id WHERE cc.unique_country_count <= 1 GROUP BY client_id UNION ALL -- 场景2:多国家合法重复,去重同客户+同国家的误操作记录 SELECT client_id, company_name, country, group_id, other_fields FROM ( SELECT c.*, ROW_NUMBER() OVER ( PARTITION BY client_id, country ORDER BY update_time DESC ) AS record_rank FROM company_clients c JOIN client_country_check cc ON c.client_id = cc.client_id WHERE cc.unique_country_count > 1 ) t WHERE t.record_rank = 1
关键注意点
- 替换
client_id为你实际的客户唯一标识字段(比如company_code)。 - 调整
ORDER BY的排序规则:如果没有update_time,可以用created_time或者其他业务优先级字段。 - 聚合函数按需选择:合并分组用
STRING_AGG(PostgreSQL)、GROUP_CONCAT(MySQL)、LISTAGG(Oracle)等。
内容的提问来源于stack exchange,提问作者Randy
相关产品推荐
相关产品推荐

