补充员工收入和亲属数据
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
# 2026-03-19 员工收入与亲属补数实施记录
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
- 当前 `ccdi_base_staff` 共 1004 名员工,其中仅 2 名员工已维护 `annual_income`
|
||||||
|
- 当前 `ccdi_staff_fmy_relation` 已存在 3004 条员工亲属数据,但只覆盖 53 名员工,且单人亲属数量集中在 42-82 条,不符合“每个员工 1-3 个亲属”的目标
|
||||||
|
- 现有员工资产表中有 1 条亲属关系被 2 条资产记录引用,补数时需要保留该关系,避免资产详情失联
|
||||||
|
|
||||||
|
## 本次处理
|
||||||
|
|
||||||
|
1. 新增增量脚本 `sql/migration/2026-03-19-backfill-staff-income-and-relatives.sql`
|
||||||
|
2. 对 `ccdi_base_staff` 中 `annual_income IS NULL` 的员工补齐年收入,保留已有收入值不覆盖
|
||||||
|
3. 识别并保留已与 `ccdi_asset_info` 建立关联的员工亲属关系
|
||||||
|
4. 清理旧的员工亲属数据后,按员工主数据重新生成每人 1-3 条亲属关系
|
||||||
|
5. 为新生成和保留的亲属统一补齐 `annual_income`、有效状态和基础元数据
|
||||||
|
|
||||||
|
## 数据规则
|
||||||
|
|
||||||
|
- 员工年收入仅补空值,使用固定公式生成,保证脚本重复执行时口径稳定
|
||||||
|
- 员工亲属数量按 `staff_id % 3 + 1` 生成,因此每名员工最终稳定为 1-3 条亲属
|
||||||
|
- 生成亲属关系类型按顺序落为 `配偶 / 父亲 / 母亲`
|
||||||
|
- 若某员工已有被资产引用的亲属,则先保留该亲属,再补齐剩余条数
|
||||||
|
|
||||||
|
## 验证项
|
||||||
|
|
||||||
|
- 执行后 `ccdi_base_staff` 的 `annual_income` 空值应为 `0`
|
||||||
|
- 执行后所有员工的亲属数量分布只允许出现 `1`、`2`、`3`
|
||||||
|
- 已挂到亲属名下的 2 条资产仍可通过保留的亲属证件号关联到员工
|
||||||
|
|
||||||
|
## 实际执行结果
|
||||||
|
|
||||||
|
- 已执行:`bin/mysql_utf8_exec.sh sql/migration/2026-03-19-backfill-staff-income-and-relatives.sql`
|
||||||
|
- 员工收入校验结果:`staff_count = 1004`,`income_null_count = 0`,`annual_income` 区间为 `120000.00 ~ 274000.00`
|
||||||
|
- 员工亲属数量分布:`1条=335人`,`2条=334人`,`3条=335人`
|
||||||
|
- 资产保留校验:员工 `330101198802020033` 名下原有测试亲属 `330101199202020044` 已保留,仍关联 `2` 条资产记录
|
||||||
306
sql/migration/2026-03-19-backfill-staff-income-and-relatives.sql
Normal file
306
sql/migration/2026-03-19-backfill-staff-income-and-relatives.sql
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
-- 1. 为尚未维护年收入的员工补齐收入
|
||||||
|
UPDATE ccdi_base_staff
|
||||||
|
SET annual_income = ROUND(
|
||||||
|
120000
|
||||||
|
+ MOD(staff_id, 9) * 18000
|
||||||
|
+ MOD(staff_id, 5) * 2500,
|
||||||
|
2
|
||||||
|
),
|
||||||
|
update_by = 'system',
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE annual_income IS NULL;
|
||||||
|
|
||||||
|
-- 2. 保留已与资产关联的员工亲属关系,避免资产详情失联
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp_staff_family_preserved;
|
||||||
|
CREATE TEMPORARY TABLE tmp_staff_family_preserved AS
|
||||||
|
SELECT
|
||||||
|
r.person_id,
|
||||||
|
r.relation_type,
|
||||||
|
r.relation_name,
|
||||||
|
r.gender,
|
||||||
|
r.birth_date,
|
||||||
|
r.relation_cert_type,
|
||||||
|
r.relation_cert_no,
|
||||||
|
r.mobile_phone1,
|
||||||
|
r.mobile_phone2,
|
||||||
|
r.annual_income,
|
||||||
|
r.wechat_no1,
|
||||||
|
r.wechat_no2,
|
||||||
|
r.wechat_no3,
|
||||||
|
r.contact_address,
|
||||||
|
r.relation_desc,
|
||||||
|
r.effective_date,
|
||||||
|
r.invalid_date,
|
||||||
|
1 AS status,
|
||||||
|
r.remark,
|
||||||
|
COALESCE(NULLIF(r.data_source, ''), 'SYSTEM') AS data_source,
|
||||||
|
1 AS is_emp_family,
|
||||||
|
0 AS is_cust_family,
|
||||||
|
COALESCE(NULLIF(r.created_by, ''), 'system') AS created_by,
|
||||||
|
COALESCE(NULLIF(r.updated_by, ''), 'system') AS updated_by
|
||||||
|
FROM ccdi_staff_fmy_relation r
|
||||||
|
WHERE r.is_emp_family = 1
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM ccdi_asset_info a
|
||||||
|
WHERE a.family_id = r.person_id
|
||||||
|
AND a.person_id = r.relation_cert_no
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp_staff_family_preserved_count;
|
||||||
|
CREATE TEMPORARY TABLE tmp_staff_family_preserved_count AS
|
||||||
|
SELECT person_id, COUNT(*) AS preserved_count
|
||||||
|
FROM tmp_staff_family_preserved
|
||||||
|
GROUP BY person_id;
|
||||||
|
|
||||||
|
-- 3. 清理旧员工亲属数据,按当前员工主数据重建每人 1-3 个亲属
|
||||||
|
DELETE FROM ccdi_staff_fmy_relation
|
||||||
|
WHERE is_emp_family = 1;
|
||||||
|
|
||||||
|
INSERT INTO ccdi_staff_fmy_relation (
|
||||||
|
person_id,
|
||||||
|
relation_type,
|
||||||
|
relation_name,
|
||||||
|
gender,
|
||||||
|
birth_date,
|
||||||
|
relation_cert_type,
|
||||||
|
relation_cert_no,
|
||||||
|
mobile_phone1,
|
||||||
|
mobile_phone2,
|
||||||
|
annual_income,
|
||||||
|
wechat_no1,
|
||||||
|
wechat_no2,
|
||||||
|
wechat_no3,
|
||||||
|
contact_address,
|
||||||
|
relation_desc,
|
||||||
|
effective_date,
|
||||||
|
invalid_date,
|
||||||
|
status,
|
||||||
|
remark,
|
||||||
|
data_source,
|
||||||
|
is_emp_family,
|
||||||
|
is_cust_family,
|
||||||
|
created_by,
|
||||||
|
create_time,
|
||||||
|
updated_by,
|
||||||
|
update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
person_id,
|
||||||
|
relation_type,
|
||||||
|
relation_name,
|
||||||
|
gender,
|
||||||
|
birth_date,
|
||||||
|
relation_cert_type,
|
||||||
|
relation_cert_no,
|
||||||
|
mobile_phone1,
|
||||||
|
mobile_phone2,
|
||||||
|
annual_income,
|
||||||
|
wechat_no1,
|
||||||
|
wechat_no2,
|
||||||
|
wechat_no3,
|
||||||
|
contact_address,
|
||||||
|
relation_desc,
|
||||||
|
COALESCE(effective_date, NOW()),
|
||||||
|
NULL,
|
||||||
|
status,
|
||||||
|
remark,
|
||||||
|
data_source,
|
||||||
|
is_emp_family,
|
||||||
|
is_cust_family,
|
||||||
|
created_by,
|
||||||
|
NOW(),
|
||||||
|
updated_by,
|
||||||
|
NOW()
|
||||||
|
FROM tmp_staff_family_preserved;
|
||||||
|
|
||||||
|
INSERT INTO ccdi_staff_fmy_relation (
|
||||||
|
person_id,
|
||||||
|
relation_type,
|
||||||
|
relation_name,
|
||||||
|
gender,
|
||||||
|
birth_date,
|
||||||
|
relation_cert_type,
|
||||||
|
relation_cert_no,
|
||||||
|
mobile_phone1,
|
||||||
|
mobile_phone2,
|
||||||
|
annual_income,
|
||||||
|
wechat_no1,
|
||||||
|
wechat_no2,
|
||||||
|
wechat_no3,
|
||||||
|
contact_address,
|
||||||
|
relation_desc,
|
||||||
|
effective_date,
|
||||||
|
invalid_date,
|
||||||
|
status,
|
||||||
|
remark,
|
||||||
|
data_source,
|
||||||
|
is_emp_family,
|
||||||
|
is_cust_family,
|
||||||
|
created_by,
|
||||||
|
create_time,
|
||||||
|
updated_by,
|
||||||
|
update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
relation_gen.person_id,
|
||||||
|
CASE relation_gen.family_seq
|
||||||
|
WHEN 1 THEN '配偶'
|
||||||
|
WHEN 2 THEN '父亲'
|
||||||
|
ELSE '母亲'
|
||||||
|
END AS relation_type,
|
||||||
|
CONCAT(
|
||||||
|
CASE MOD(relation_gen.staff_id + relation_gen.family_seq, 12)
|
||||||
|
WHEN 0 THEN '王'
|
||||||
|
WHEN 1 THEN '李'
|
||||||
|
WHEN 2 THEN '张'
|
||||||
|
WHEN 3 THEN '刘'
|
||||||
|
WHEN 4 THEN '陈'
|
||||||
|
WHEN 5 THEN '杨'
|
||||||
|
WHEN 6 THEN '黄'
|
||||||
|
WHEN 7 THEN '赵'
|
||||||
|
WHEN 8 THEN '周'
|
||||||
|
WHEN 9 THEN '吴'
|
||||||
|
WHEN 10 THEN '徐'
|
||||||
|
ELSE '孙'
|
||||||
|
END,
|
||||||
|
CASE MOD(relation_gen.staff_id * 3 + relation_gen.family_seq, 12)
|
||||||
|
WHEN 0 THEN '建'
|
||||||
|
WHEN 1 THEN '国'
|
||||||
|
WHEN 2 THEN '晓'
|
||||||
|
WHEN 3 THEN '海'
|
||||||
|
WHEN 4 THEN '文'
|
||||||
|
WHEN 5 THEN '玉'
|
||||||
|
WHEN 6 THEN '志'
|
||||||
|
WHEN 7 THEN '秀'
|
||||||
|
WHEN 8 THEN '德'
|
||||||
|
WHEN 9 THEN '丽'
|
||||||
|
WHEN 10 THEN '明'
|
||||||
|
ELSE '红'
|
||||||
|
END,
|
||||||
|
CASE MOD(relation_gen.staff_id * 7 + relation_gen.family_seq, 12)
|
||||||
|
WHEN 0 THEN '华'
|
||||||
|
WHEN 1 THEN '芳'
|
||||||
|
WHEN 2 THEN '伟'
|
||||||
|
WHEN 3 THEN '兰'
|
||||||
|
WHEN 4 THEN '杰'
|
||||||
|
WHEN 5 THEN '英'
|
||||||
|
WHEN 6 THEN '敏'
|
||||||
|
WHEN 7 THEN '娜'
|
||||||
|
WHEN 8 THEN '强'
|
||||||
|
WHEN 9 THEN '静'
|
||||||
|
WHEN 10 THEN '勇'
|
||||||
|
ELSE '霞'
|
||||||
|
END
|
||||||
|
) AS relation_name,
|
||||||
|
CASE relation_gen.family_seq
|
||||||
|
WHEN 1 THEN CASE MOD(relation_gen.staff_id, 2) WHEN 0 THEN 'F' ELSE 'M' END
|
||||||
|
WHEN 2 THEN 'M'
|
||||||
|
ELSE 'F'
|
||||||
|
END AS gender,
|
||||||
|
CASE relation_gen.family_seq
|
||||||
|
WHEN 1 THEN DATE_ADD('1982-01-01', INTERVAL MOD(relation_gen.staff_id * 17 + relation_gen.family_seq, 7000) DAY)
|
||||||
|
WHEN 2 THEN DATE_ADD('1957-01-01', INTERVAL MOD(relation_gen.staff_id * 11 + relation_gen.family_seq, 8000) DAY)
|
||||||
|
ELSE DATE_ADD('1960-01-01', INTERVAL MOD(relation_gen.staff_id * 13 + relation_gen.family_seq, 8000) DAY)
|
||||||
|
END AS birth_date,
|
||||||
|
'居民身份证' AS relation_cert_type,
|
||||||
|
CONCAT(
|
||||||
|
'320101',
|
||||||
|
DATE_FORMAT(
|
||||||
|
DATE_ADD('1970-01-01', INTERVAL MOD(relation_gen.staff_id * (relation_gen.family_seq + 7), 15000) DAY),
|
||||||
|
'%Y%m%d'
|
||||||
|
),
|
||||||
|
LPAD(MOD(relation_gen.staff_id * 10 + relation_gen.family_seq, 10000), 4, '0')
|
||||||
|
) AS relation_cert_no,
|
||||||
|
CONCAT(
|
||||||
|
'13',
|
||||||
|
LPAD(MOD(relation_gen.staff_id * 97 + relation_gen.family_seq * 13, 1000000000), 9, '0')
|
||||||
|
) AS mobile_phone1,
|
||||||
|
NULL AS mobile_phone2,
|
||||||
|
CASE relation_gen.family_seq
|
||||||
|
WHEN 1 THEN ROUND(80000 + MOD(relation_gen.staff_id, 8) * 12000, 2)
|
||||||
|
WHEN 2 THEN ROUND(50000 + MOD(relation_gen.staff_id, 7) * 7000, 2)
|
||||||
|
ELSE ROUND(45000 + MOD(relation_gen.staff_id, 7) * 6500, 2)
|
||||||
|
END AS annual_income,
|
||||||
|
NULL AS wechat_no1,
|
||||||
|
NULL AS wechat_no2,
|
||||||
|
NULL AS wechat_no3,
|
||||||
|
CONCAT('员工', relation_gen.staff_name, '家庭住址') AS contact_address,
|
||||||
|
CONCAT('2026-03-19补数脚本生成的', CASE relation_gen.family_seq WHEN 1 THEN '配偶' WHEN 2 THEN '父亲' ELSE '母亲' END) AS relation_desc,
|
||||||
|
NOW() AS effective_date,
|
||||||
|
NULL AS invalid_date,
|
||||||
|
1 AS status,
|
||||||
|
'2026-03-19补数脚本生成' AS remark,
|
||||||
|
'SYSTEM' AS data_source,
|
||||||
|
1 AS is_emp_family,
|
||||||
|
0 AS is_cust_family,
|
||||||
|
'system' AS created_by,
|
||||||
|
NOW() AS create_time,
|
||||||
|
'system' AS updated_by,
|
||||||
|
NOW() AS update_time
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
s.staff_id,
|
||||||
|
s.name AS staff_name,
|
||||||
|
s.id_card AS person_id,
|
||||||
|
IFNULL(p.preserved_count, 0) + seq.rel_seq AS family_seq
|
||||||
|
FROM ccdi_base_staff s
|
||||||
|
LEFT JOIN tmp_staff_family_preserved_count p
|
||||||
|
ON p.person_id = s.id_card
|
||||||
|
JOIN (
|
||||||
|
SELECT 1 AS rel_seq
|
||||||
|
UNION ALL
|
||||||
|
SELECT 2 AS rel_seq
|
||||||
|
UNION ALL
|
||||||
|
SELECT 3 AS rel_seq
|
||||||
|
) seq
|
||||||
|
ON seq.rel_seq <= GREATEST(MOD(s.staff_id, 3) + 1 - IFNULL(p.preserved_count, 0), 0)
|
||||||
|
) relation_gen;
|
||||||
|
|
||||||
|
-- 4. 补齐保留亲属的收入,并统一有效状态
|
||||||
|
UPDATE ccdi_staff_fmy_relation
|
||||||
|
SET annual_income = COALESCE(
|
||||||
|
annual_income,
|
||||||
|
ROUND(
|
||||||
|
CASE relation_type
|
||||||
|
WHEN '配偶' THEN 80000 + MOD(CRC32(CONCAT(person_id, '-', relation_cert_no)), 10) * 6000
|
||||||
|
WHEN '父亲' THEN 50000 + MOD(CRC32(CONCAT(person_id, '-', relation_cert_no)), 8) * 4000
|
||||||
|
WHEN '母亲' THEN 45000 + MOD(CRC32(CONCAT(person_id, '-', relation_cert_no)), 8) * 3500
|
||||||
|
ELSE 60000 + MOD(CRC32(CONCAT(person_id, '-', relation_cert_no)), 10) * 5000
|
||||||
|
END,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
),
|
||||||
|
status = 1,
|
||||||
|
invalid_date = NULL,
|
||||||
|
data_source = COALESCE(NULLIF(data_source, ''), 'SYSTEM'),
|
||||||
|
is_emp_family = 1,
|
||||||
|
is_cust_family = 0,
|
||||||
|
updated_by = 'system',
|
||||||
|
update_time = NOW()
|
||||||
|
WHERE is_emp_family = 1;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
COUNT(*) AS staff_count,
|
||||||
|
SUM(CASE WHEN annual_income IS NULL THEN 1 ELSE 0 END) AS income_null_count
|
||||||
|
FROM ccdi_base_staff;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
rel_cnt,
|
||||||
|
COUNT(*) AS staff_num
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
s.staff_id,
|
||||||
|
COUNT(r.id) AS rel_cnt
|
||||||
|
FROM ccdi_base_staff s
|
||||||
|
LEFT JOIN ccdi_staff_fmy_relation r
|
||||||
|
ON r.person_id = s.id_card
|
||||||
|
AND r.is_emp_family = 1
|
||||||
|
GROUP BY s.staff_id
|
||||||
|
) relation_summary
|
||||||
|
GROUP BY rel_cnt
|
||||||
|
ORDER BY rel_cnt;
|
||||||
Reference in New Issue
Block a user