目录
一、前言
二、数据去重应用场景
三、数据去重案例(GaussDB)
1、示例场景描述
2、定义重复数据
3、制定去重规则
4、创建测试数据(GaussDB)
5、编写去重方法(GaussDB)
6、附:全字段去重
四、数据去重效率提升建议
五、总结
数据去重在数据库中是比较常见的操作。复杂的业务场景、多业务线的数据来源等等,都会带来重复数据的存储。本文以GaussDB数据库为实验平台,将为大家详细讲解如何去重。
实战业务场景 + GaussDB数据库
以保险行业的客户信息除重为例,为防止坐席重复联系客户(容易造成客户投诉),需要将客户进行唯一身份识别。存在以下两种情况,需要将其识别成一个人(唯一),这时候就需要进行数据去重的动作。
通过“姓名+证件类型+证件号”将其识别为一个人,即只要这三个字段重复,就认为这些数据行为重复数据。 (当然还有更复杂的场景,例如,“姓名+证件类型+证件号+手机号+车牌号”等,本次不做详细介绍)。
1)多选一
2)多合一
客户信息字段主要包含“姓名、性别、出生年月日、证件类型、证件号、来源、是否有车、是否有房、婚姻状态、手机号、……”等信息。
--创建客户信息表
CREATE TABLE customer(
name VARCHAR(20)
,sex INT
,birthday VARCHAR(10)
,ID_type INT
,ID_number VARCHAR(20)
,source VARCHAR(10)
,IS_car INT
,IS_house INT
,marital_status INT
,tel_number VARCHAR(15)
);
--插入测试数据
INSERT INTO customer VALUES('张三','1','1988-01-01','1','61010019880101****','寿险','1','1','1','');
INSERT INTO customer VALUES('张三','1','1988-01-01','1','61010019880101****','车险','1','0','1','');
INSERT INTO customer VALUES('张三','1','1988-01-01','1','61010019880101****','','','','','186****0701');
INSERT INTO customer VALUES('李四','1','1989-01-02','1','61010019890102****','寿险','1','1','1','');
INSERT INTO customer VALUES('李四','1','1989-01-02','1','61010019890102****','车险','1','0','1','');
INSERT INTO customer VALUES('李四','1','1989-01-02','1','61010019890102****','','','','','186****0702');
--查看结果
SELECT * FROM customer;
Tip: 部分为INT类型的字段值取字典表的值,此处省。
以下示例中不包含过多的数据清洗、数据脱敏、业务逻辑等的处理,这些步骤均建议进行“前置”处理。本次示例重点描述去重的过程。
1)随机保留:根据业务逻辑,随机保留一条记录。
SELECT *
FROM (SELECT *
,ROW_NUMBER() OVER (PARTITION BY name,id_type,id_number ) as row_num
FROM customer)
WHERE row_num = 1;
说明:
2)按优先级保留:根据业务逻辑,优先保留有手机号的一条记录,如果有多条记录含有手机号或有没有手机号,则在此基础上随机保留。
--保留含有手机号的记录行
SELECT t.*
FROM (SELECT *
,ROW_NUMBER() OVER (PARTITION BY name,id_type,id_number ORDER BY tel_number ASC) as row_num
FROM customer) t
WHERE t.row_num = 1;
说明:
3)合并保留:根据业务逻辑,合并完整性高、准确性高的字段信息。例如优先将含有手机号的记录行进行补齐,需要补齐的字段有“是否有车、是否有房、婚姻状况”,其取值是来源为“车险”的对应记录。
--合并保留
SELECT t1.name
,t1.sex
,t1.birthday
,t1.id_type
,t1.id_number
,t1.source
,t2.is_car
,t2.is_house
,t2.marital_status
,t1.tel_number
FROM
(SELECT t.*
FROM (SELECT *
,ROW_NUMBER() OVER (PARTITION BY name,id_type,id_number ORDER BY tel_number ASC) as row_num
FROM customer) t
WHERE t.row_num = 1) t1
LEFT JOIN
(SELECT *
FROM customer
WHERE source ='车险' and is_car IS NOT NULL AND is_house IS NOT NULL AND marital_status IS NOT NULL) t2
ON t1.name =t2.name
and t1.id_type=t2.id_type
and t1.id_number=t2.id_number
说明:
t1 表是优先保留含有手机的记录行(去重),并作为主表,t2表是需要补齐的字段来源表。两张表通过“姓名+证件类型+证件号码”进行关联,然后合并需要的信息。
在数据库应用时,例如,重复误操作、数据翻倍等原因造成的全字段重复,此时也要进行去重。 那除了前面介绍的3种方式外,大家还可以使用关键字DISTINCT、UNION 进行去重,但需要注意其数据量及SQL 性能。 (大家自行测试)
1) DISTINCT (假设全部有如下三个字段)
2) UNION(假设全部有如下三个字段)
最好的去重其实是在数据源头就进行“拦截”。当然了, 因业务流转也不可能完全避免,但是我们可以提高去重的效率:
数据去重涉及到的面非常广,包括重复数据的发现、去重规则的定义、去重的方法与效率、去重的困难与挑战等等。但是,去重原则只有一个,那就是以业务为导向。根据业务需求去定义重复数据、制定去重规则和方案。在GaussDB数据库的使用过程,我们同样会遇到去重的场景。本文从应用背景、案例、去重方案等方面给大家做了介绍,欢迎测试、交流。
——结束