migration_drainage_waterlogging_duty.sql 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. -- 易积水点:责任单位 / 责任人改为关联系统部门与用户
  2. --
  3. -- 背景:原表只存 duty_unit / duty_person / duty_phone 三个自由文本,
  4. -- 与 sys_dept / sys_user 没有任何关联。带来的问题是:
  5. -- · 同一个部门被手输成多种写法,统计口径无法收敛;
  6. -- · 人员调岗、改名后台账失真,也点不进去看这个人是谁;
  7. -- · 联系电话靠手填,容易与人事信息不一致。
  8. --
  9. -- 本脚本做两件事:
  10. -- 1. 幂等补两列:duty_dept_id(sys_dept.dept_id)、duty_user_id(sys_user.user_id);
  11. -- 2. 尽力回填:按名称精确匹配 sys_dept.dept_name / sys_user.nick_name,
  12. -- 匹配上的补 ID,匹配不上的保持 NULL(不猜、不改已有文本)。
  13. --
  14. -- 保留原有三列作为「快照」:
  15. -- duty_unit / duty_person / duty_phone 继续存当时的名称与号码。
  16. -- 列表、地图、详情直接读快照,不必回表 join;人员改名也不影响历史记录。
  17. --
  18. -- 前置:结束上一次失败执行遗留的 aborted 事务(事务外执行只会告警,不报错)
  19. ROLLBACK;
  20. BEGIN;
  21. -- =====================================================================
  22. -- 1. 幂等补列
  23. -- =====================================================================
  24. DO $$
  25. DECLARE
  26. col record;
  27. BEGIN
  28. IF to_regclass('app_user.drainage_waterlogging_point') IS NULL THEN
  29. RAISE NOTICE '表 app_user.drainage_waterlogging_point 不存在,请先执行 migration_drainage_waterlogging_point.sql';
  30. RETURN;
  31. END IF;
  32. FOR col IN
  33. SELECT * FROM (VALUES
  34. ('duty_dept_id', 'bigint'),
  35. ('duty_user_id', 'bigint')
  36. ) AS x(name, type)
  37. LOOP
  38. IF NOT EXISTS (
  39. SELECT 1 FROM information_schema.columns
  40. WHERE table_schema = 'app_user'
  41. AND table_name = 'drainage_waterlogging_point'
  42. AND column_name = col.name
  43. ) THEN
  44. EXECUTE format('ALTER TABLE app_user.drainage_waterlogging_point ADD COLUMN %I %s',
  45. col.name, col.type);
  46. RAISE NOTICE '已补列:%', col.name;
  47. END IF;
  48. END LOOP;
  49. END $$;
  50. COMMENT ON COLUMN app_user.drainage_waterlogging_point.duty_dept_id IS '责任单位(sys_dept.dept_id,duty_unit 存其名称快照)';
  51. COMMENT ON COLUMN app_user.drainage_waterlogging_point.duty_user_id IS '责任人(sys_user.user_id,duty_person / duty_phone 存其姓名与电话快照)';
  52. CREATE INDEX IF NOT EXISTS idx_dwp_duty_dept ON app_user.drainage_waterlogging_point (duty_dept_id);
  53. CREATE INDEX IF NOT EXISTS idx_dwp_duty_user ON app_user.drainage_waterlogging_point (duty_user_id);
  54. -- =====================================================================
  55. -- 2. 存量数据回填(只做精确匹配,匹配不上就留空)
  56. -- 同一名称对应多个部门/用户时取 ID 最小的那个,避免一对多歧义放大。
  57. -- =====================================================================
  58. DO $$
  59. DECLARE
  60. v_dept integer := 0;
  61. v_user integer := 0;
  62. BEGIN
  63. IF to_regclass('app_user.drainage_waterlogging_point') IS NULL THEN
  64. RETURN;
  65. END IF;
  66. -- 2.1 责任单位:duty_unit 文本 → dept_id
  67. UPDATE app_user.drainage_waterlogging_point p
  68. SET duty_dept_id = d.dept_id
  69. FROM (
  70. SELECT dept_name, MIN(dept_id) AS dept_id
  71. FROM app_user.sys_dept
  72. WHERE del_flag = '0'
  73. GROUP BY dept_name
  74. ) d
  75. WHERE p.duty_dept_id IS NULL
  76. AND p.duty_unit IS NOT NULL
  77. AND trim(p.duty_unit) = d.dept_name;
  78. GET DIAGNOSTICS v_dept = ROW_COUNT;
  79. -- 2.2 责任人:duty_person 文本 → user_id
  80. UPDATE app_user.drainage_waterlogging_point p
  81. SET duty_user_id = u.user_id
  82. FROM (
  83. SELECT nick_name, MIN(user_id) AS user_id
  84. FROM app_user.sys_user
  85. WHERE del_flag = '0'
  86. GROUP BY nick_name
  87. ) u
  88. WHERE p.duty_user_id IS NULL
  89. AND p.duty_person IS NOT NULL
  90. AND trim(p.duty_person) = u.nick_name;
  91. GET DIAGNOSTICS v_user = ROW_COUNT;
  92. RAISE NOTICE '存量回填:责任单位匹配 % 条,责任人匹配 % 条', v_dept, v_user;
  93. END $$;
  94. -- =====================================================================
  95. -- 3. 结果核验(可选,取消注释执行)
  96. -- =====================================================================
  97. -- 还没关联上的记录(需要人工在页面上重新选一次部门/人员)
  98. -- SELECT point_code, point_name, duty_unit, duty_person
  99. -- FROM app_user.drainage_waterlogging_point
  100. -- WHERE del_flag = '0'
  101. -- AND ((duty_unit IS NOT NULL AND duty_dept_id IS NULL)
  102. -- OR (duty_person IS NOT NULL AND duty_user_id IS NULL));
  103. COMMIT;