liusheng
5 天以前 fb89df539c6293a41933e445df25fa9b8047ba18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
-- ============================================================================
-- 把 pat_med_inhosp 的「科室 / 病区」回填到 service_subtask(在院 4 列 + 离院 4 列)
-- 生成日期:2026-11-06(v2:修正 join 键 + 合并离院维度)
-- 适用:MySQL 8.0 / 5.7(未用 CTE、窗口函数)
--
-- ⚠️ 前置条件:先执行过 sql/rename_service_subtask_dims_20261106.sql(列已改名)。
--
-- ⚠️⚠️ join 键(v1 写错过,这里更正):
--     service_subtask.inhospid 存的是 **pat_med_inhosp.inhospid**(业务主键),不是 id。
--     证据:VisitInhospMapper.xml#selectForScan 查的是 b.inhospid;
--           VisitSubtaskFactory 里是 d.setInhospid(inhosp.getInhospid())。
--     门诊侧例外:PatMedOuthospServiceDelegatingImpl 用的是 pat_med_outhosp.getId(),
--     所以 pat_med_outhosp 的 id 会和 pat_med_inhosp.inhospid 撞号 → 必须排除 service_type='3'。
--
-- 字段映射(8 列,注意「在院病区」和「出院病区」不是一回事)
--   在院维度(本次新增列)
--     service_subtask.hospitaldistrictcode/name      ← pat_med_inhosp.hospitaldistrictcode/name      (在院病区)
--     service_subtask.deptcode/name                   ← pat_med_inhosp.deptcode/name                  (在院科室)
--   离院/出院维度(老列,原 deptcode/deptname 改名而来)
--     service_subtask.leaveldeptcode/name             ← pat_med_inhosp.leaveldeptcode/name            (出院科室)
--     service_subtask.leavehospitaldistrictcode/name  ← pat_med_inhosp.leavehospitaldistrictcode/name (出院病区)
--
-- 安全策略
--   1) 全部用 COALESCE「目标列为空才写」→ **不覆盖任何已有值**,可重复执行;
--   2) 更新前先备份受影响行的这 8 列旧值(§2);
--   3) 大表分批模板见 §6。
-- ============================================================================
 
 
-- ----------------------------------------------------------------------------
-- 0) 前置自查
-- ----------------------------------------------------------------------------
SHOW FULL COLUMNS FROM service_subtask LIKE '%dept%';
SHOW FULL COLUMNS FROM service_subtask LIKE 'hospitaldistrict%';
SHOW FULL COLUMNS FROM pat_med_inhosp LIKE '%dept%';
SHOW FULL COLUMNS FROM pat_med_inhosp LIKE 'hospitaldistrict%';
 
 
-- ----------------------------------------------------------------------------
-- 1) 影响面评估(先看数,再动手)
-- ----------------------------------------------------------------------------
 
-- 1.1 能 join 上的子任务数 + 8 列里各有多少是空的
SELECT COUNT(*)                                                                   AS joined_rows,
       SUM(hospitaldistrictcode      IS NULL OR hospitaldistrictcode      = '')    AS hd_code_empty,
       SUM(hospitaldistrictname      IS NULL OR hospitaldistrictname      = '')    AS hd_name_empty,
       SUM(deptcode                  IS NULL OR deptcode                  = '')    AS dept_code_empty,
       SUM(deptname                  IS NULL OR deptname                  = '')    AS dept_name_empty,
       SUM(leaveldeptcode            IS NULL OR leaveldeptcode            = '')    AS lv_dept_code_empty,
       SUM(leaveldeptname            IS NULL OR leaveldeptname            = '')    AS lv_dept_name_empty,
       SUM(leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '')    AS lv_hd_code_empty,
       SUM(leavehospitaldistrictname IS NULL OR leavehospitaldistrictname = '')    AS lv_hd_name_empty
  FROM service_subtask s
  JOIN pat_med_inhosp b
    ON b.inhospid = s.inhospid
   AND b.patid   = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
   AND (s.hosp_type IS NULL OR s.hosp_type <> '8');
 
-- 1.2 按 service_type 看分布(2/13 出院随访、17/18 入院宣教/入院随访、6/14/15/16 满意度子任务)
SELECT s.service_type,
       COUNT(*)                                                                  AS cnt,
       SUM(s.deptcode            IS NULL OR s.deptcode            = '')          AS dept_empty,
       SUM(s.hospitaldistrictcode IS NULL OR s.hospitaldistrictcode = '')        AS hd_empty,
       SUM(s.leaveldeptcode      IS NULL OR s.leaveldeptcode      = '')          AS lv_dept_empty,
       SUM(s.leavehospitaldistrictcode IS NULL OR s.leavehospitaldistrictcode = '') AS lv_hd_empty
  FROM service_subtask s
  JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
 GROUP BY s.service_type
 ORDER BY cnt DESC;
 
-- 1.3 join 不上的诊断:inhospid 有值、但 patid 对不上
SELECT s.service_type,
       COUNT(*) AS unmatched
  FROM service_subtask s
  LEFT JOIN pat_med_inhosp b
         ON b.inhospid = s.inhospid
        AND b.patid   = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
   AND b.inhospid IS NULL
 GROUP BY s.service_type
 ORDER BY unmatched DESC;
 
-- 1.4 源表 inhospid 是否唯一(不唯一会让 UPDATE 取到其中一行,结果不确定)
SELECT inhospid, COUNT(*) AS c, COUNT(DISTINCT patid) AS pats
  FROM pat_med_inhosp
 WHERE inhospid IS NOT NULL
 GROUP BY inhospid
HAVING c > 1
 ORDER BY c DESC
 LIMIT 20;
 
-- 1.5 一条子任务是否会被多行源数据命中(应为 0;有值就先把 §1.4 的重复处理干净)
SELECT COUNT(*) AS subtask_rows, COUNT(*) - COUNT(DISTINCT s.id) AS dup_hit
  FROM service_subtask s
  JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3';
 
 
-- ----------------------------------------------------------------------------
-- 2) 备份受影响行的 8 列旧值(回滚见 §7)
-- ----------------------------------------------------------------------------
CREATE TABLE bak_service_subtask_dept_20261106 AS
SELECT s.id,
       s.service_type,
       s.hosp_type,
       s.inhospid,
       s.patid,
       s.leaveldeptcode,
       s.leaveldeptname,
       s.leavehospitaldistrictcode,
       s.leavehospitaldistrictname,
       s.hospitaldistrictcode,
       s.hospitaldistrictname,
       s.deptcode,
       s.deptname
  FROM service_subtask s
  JOIN pat_med_inhosp b
    ON b.inhospid = s.inhospid
   AND b.patid   = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
   AND (s.hosp_type IS NULL OR s.hosp_type <> '8')
   AND (  NULLIF(TRIM(s.hospitaldistrictcode), '')       IS NULL
       OR NULLIF(TRIM(s.hospitaldistrictname), '')       IS NULL
       OR NULLIF(TRIM(s.deptcode), '')                   IS NULL
       OR NULLIF(TRIM(s.deptname), '')                   IS NULL
       OR NULLIF(TRIM(s.leaveldeptcode), '')             IS NULL
       OR NULLIF(TRIM(s.leaveldeptname), '')             IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictcode), '')  IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictname), '')  IS NULL );
 
SELECT COUNT(*) AS backup_rows FROM bak_service_subtask_dept_20261106;
 
 
-- ----------------------------------------------------------------------------
-- 3) 主回填:在院 4 列 + 离院 4 列(只补空,不覆盖;可重复执行)
-- ----------------------------------------------------------------------------
UPDATE service_subtask s
  JOIN pat_med_inhosp b
    ON b.inhospid = s.inhospid
   AND b.patid   = s.patid
   SET s.hospitaldistrictcode      = COALESCE(NULLIF(TRIM(s.hospitaldistrictcode), ''),      b.hospitaldistrictcode),
       s.hospitaldistrictname      = COALESCE(NULLIF(TRIM(s.hospitaldistrictname), ''),      b.hospitaldistrictname),
       s.deptcode                  = COALESCE(NULLIF(TRIM(s.deptcode), ''),                  b.deptcode),
       s.deptname                  = COALESCE(NULLIF(TRIM(s.deptname), ''),                  b.deptname),
       s.leaveldeptcode            = COALESCE(NULLIF(TRIM(s.leaveldeptcode), ''),            b.leaveldeptcode),
       s.leaveldeptname            = COALESCE(NULLIF(TRIM(s.leaveldeptname), ''),            b.leaveldeptname),
       s.leavehospitaldistrictcode = COALESCE(NULLIF(TRIM(s.leavehospitaldistrictcode), ''), b.leavehospitaldistrictcode),
       s.leavehospitaldistrictname = COALESCE(NULLIF(TRIM(s.leavehospitaldistrictname), ''), b.leavehospitaldistrictname)
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'                        -- 门诊随访的 inhospid 是 pat_med_outhosp.id
   AND (s.hosp_type IS NULL OR s.hosp_type <> '8')  -- 扫码生成的虚拟患者
   AND (  NULLIF(TRIM(s.hospitaldistrictcode), '')      IS NULL
       OR NULLIF(TRIM(s.hospitaldistrictname), '')      IS NULL
       OR NULLIF(TRIM(s.deptcode), '')                  IS NULL
       OR NULLIF(TRIM(s.deptname), '')                  IS NULL
       OR NULLIF(TRIM(s.leaveldeptcode), '')            IS NULL
       OR NULLIF(TRIM(s.leaveldeptname), '')            IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictcode), '') IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictname), '') IS NULL );
 
 
-- ----------------------------------------------------------------------------
-- 4) 口径说明 + 可选的"强制改写"
--
--    4.1 为什么离院 4 列也用「只补空」:
--        service_type = 17/18(入院宣教/入院随访)生成时走 type 4/5 分支,
--        `leaveldeptcode/name` 里存的其实是**入院科室**(d.setLeaveldeptcode(inhosp.getDeptcode()))。
--        这些行非空 → §3 不会动它们;若为空则会被补成 pat_med_inhosp.leaveldeptcode
--        (住院患者通常为空 → 等于没变)。
--        出院随访(2/13)与满意度子任务(6/14/15/16)的离院 4 列生成时本来就取自
--        pat_med_inhosp,只可能是历史脏数据为空,补空即修数据。
--
--    4.2 如果你要的是"17/18 也统一成出院科室口径",用下面这段(**会覆盖**,先跑 §2 备份):
-- ----------------------------------------------------------------------------
-- UPDATE service_subtask s
--   JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
--    SET s.leaveldeptcode            = b.leaveldeptcode,
--        s.leaveldeptname            = b.leaveldeptname,
--        s.leavehospitaldistrictcode = b.leavehospitaldistrictcode,
--        s.leavehospitaldistrictname = b.leavehospitaldistrictname
--  WHERE s.inhospid IS NOT NULL
--    AND s.service_type IN ('17', '18')
--    AND (NULLIF(TRIM(b.leaveldeptcode), '') IS NOT NULL
--         OR NULLIF(TRIM(b.leavehospitaldistrictcode), '') IS NOT NULL);
 
 
-- ----------------------------------------------------------------------------
-- 5) 【可选】全都强制覆盖版("原来有值但是错的"时用)
--    把 §3 的 COALESCE(...) 换成直接赋值,并去掉 WHERE 里那串「目标列为空」条件:
--      SET s.hospitaldistrictcode = b.hospitaldistrictcode,
--          s.hospitaldistrictname = b.hospitaldistrictname,
--          s.deptcode = b.deptcode, s.deptname = b.deptname,
--          s.leaveldeptcode = b.leaveldeptcode, s.leaveldeptname = b.leaveldeptname,
--          s.leavehospitaldistrictcode = b.leavehospitaldistrictcode,
--          s.leavehospitaldistrictname = b.leavehospitaldistrictname
--    ⚠️ pat_med_inhosp.dept* 会被「在院信息刷新」定时任务按 HIS 当前科室改写,
--       覆盖后可能把"出院当时的科室"改成"现在 HIS 里的科室"。覆盖前务必先备份。
-- ----------------------------------------------------------------------------
 
 
-- ----------------------------------------------------------------------------
-- 6) 大表分批模板(多表 UPDATE 不支持 LIMIT,用 id 区间;每段单独提交)
--    先查范围:SELECT MIN(id), MAX(id) FROM service_subtask;
-- ----------------------------------------------------------------------------
-- UPDATE service_subtask s
--   JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
--    SET s.hospitaldistrictcode      = COALESCE(NULLIF(TRIM(s.hospitaldistrictcode), ''),      b.hospitaldistrictcode),
--        s.hospitaldistrictname      = COALESCE(NULLIF(TRIM(s.hospitaldistrictname), ''),      b.hospitaldistrictname),
--        s.deptcode                  = COALESCE(NULLIF(TRIM(s.deptcode), ''),                  b.deptcode),
--        s.deptname                  = COALESCE(NULLIF(TRIM(s.deptname), ''),                  b.deptname),
--        s.leaveldeptcode            = COALESCE(NULLIF(TRIM(s.leaveldeptcode), ''),            b.leaveldeptcode),
--        s.leaveldeptname            = COALESCE(NULLIF(TRIM(s.leaveldeptname), ''),            b.leaveldeptname),
--        s.leavehospitaldistrictcode = COALESCE(NULLIF(TRIM(s.leavehospitaldistrictcode), ''), b.leavehospitaldistrictcode),
--        s.leavehospitaldistrictname = COALESCE(NULLIF(TRIM(s.leavehospitaldistrictname), ''), b.leavehospitaldistrictname)
--  WHERE s.id > 1 AND s.id <= 50000
--    AND s.inhospid IS NOT NULL
--    AND s.service_type <> '3'
--    AND (s.hosp_type IS NULL OR s.hosp_type <> '8')
--    AND (  NULLIF(TRIM(s.hospitaldistrictcode), '')      IS NULL
--        OR NULLIF(TRIM(s.hospitaldistrictname), '')      IS NULL
--        OR NULLIF(TRIM(s.deptcode), '')                  IS NULL
--        OR NULLIF(TRIM(s.deptname), '')                  IS NULL
--        OR NULLIF(TRIM(s.leaveldeptcode), '')            IS NULL
--        OR NULLIF(TRIM(s.leaveldeptname), '')            IS NULL
--        OR NULLIF(TRIM(s.leavehospitaldistrictcode), '') IS NULL
--        OR NULLIF(TRIM(s.leavehospitaldistrictname), '') IS NULL );
 
 
-- ----------------------------------------------------------------------------
-- 7) 回滚(按 §2 备份表还原 8 列)
-- ----------------------------------------------------------------------------
-- UPDATE service_subtask s
--   JOIN bak_service_subtask_dept_20261106 k ON k.id = s.id
--    SET s.hospitaldistrictcode      = k.hospitaldistrictcode,
--        s.hospitaldistrictname      = k.hospitaldistrictname,
--        s.deptcode                  = k.deptcode,
--        s.deptname                  = k.deptname,
--        s.leaveldeptcode            = k.leaveldeptcode,
--        s.leaveldeptname            = k.leaveldeptname,
--        s.leavehospitaldistrictcode = k.leavehospitaldistrictcode,
--        s.leavehospitaldistrictname = k.leavehospitaldistrictname;
 
 
-- ----------------------------------------------------------------------------
-- 8) 回填后核对
-- ----------------------------------------------------------------------------
 
-- 8.1 还剩多少空(应接近 0;剩下的基本是 §1.3/§1.4 命中不了的)
SELECT COUNT(*)                                                                    AS still_empty_rows,
       SUM(hospitaldistrictcode      IS NULL OR hospitaldistrictcode      = '')     AS hd_code_empty,
       SUM(hospitaldistrictname      IS NULL OR hospitaldistrictname      = '')     AS hd_name_empty,
       SUM(deptcode                  IS NULL OR deptcode                  = '')     AS dept_code_empty,
       SUM(deptname                  IS NULL OR deptname                  = '')     AS dept_name_empty,
       SUM(leaveldeptcode            IS NULL OR leaveldeptcode            = '')     AS lv_dept_code_empty,
       SUM(leaveldeptname            IS NULL OR leaveldeptname            = '')     AS lv_dept_name_empty,
       SUM(leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '')     AS lv_hd_code_empty,
       SUM(leavehospitaldistrictname IS NULL OR leavehospitaldistrictname = '')     AS lv_hd_name_empty
  FROM service_subtask s
  JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
   AND (s.hosp_type IS NULL OR s.hosp_type <> '8')
   AND (  NULLIF(TRIM(s.hospitaldistrictcode), '')      IS NULL
       OR NULLIF(TRIM(s.hospitaldistrictname), '')      IS NULL
       OR NULLIF(TRIM(s.deptcode), '')                  IS NULL
       OR NULLIF(TRIM(s.deptname), '')                  IS NULL
       OR NULLIF(TRIM(s.leaveldeptcode), '')            IS NULL
       OR NULLIF(TRIM(s.leaveldeptname), '')            IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictcode), '') IS NULL
       OR NULLIF(TRIM(s.leavehospitaldistrictname), '') IS NULL );
 
-- 8.2 逐行对照抽检(两边是否一致)
SELECT s.id, s.service_type, s.inhospid,
       s.deptcode                  AS sub_dept,    b.deptcode                  AS inhosp_dept,
       s.hospitaldistrictcode      AS sub_hd,      b.hospitaldistrictcode      AS inhosp_hd,
       s.leaveldeptcode            AS sub_lv_dept, b.leaveldeptcode            AS inhosp_lv_dept,
       s.leavehospitaldistrictcode AS sub_lv_hd,   b.leavehospitaldistrictcode AS inhosp_lv_hd
  FROM service_subtask s
  JOIN pat_med_inhosp b ON b.inhospid = s.inhospid AND b.patid = s.patid
 WHERE s.inhospid IS NOT NULL
   AND s.service_type <> '3'
 ORDER BY s.id DESC
 LIMIT 50;