-- ============================================================================ -- 把「问卷库模板」题目的选项默认值(svy_lib_template_targetoption.default_value) -- 同步到「问卷任务模板」题目选项(svy_task_template_targetoption.default_value) -- -- 表名说明(问题选项的默认值其实不在 script 表里,而在 option 表里): -- 库 题目 svy_lib_template_script ── id ← scriptid ── 库 选项 svy_lib_template_targetoption -- 任务 题目 svy_task_template_script ── id ← scriptid ── 任务 选项 svy_task_template_targetoption -- default_value 语义:1=否(默认值),2=是(默认选项),NULL=未设置 -- -- 任务模板 → 库模板 的映射链(实测 smartor_nhfy): -- svy_task_template_script.templateid -- = svy_task_template.id -- → svy_task_template.templateid = svy_lib_template.svyid -- → svy_lib_template_script.svyid,题面 script_content 相同即同一道题 -- → svy_lib_template_targetoption.scriptid = svy_lib_template_script.id -- 且 optioncontent 相同即同一个选项 -- -- 实测覆盖(2026-11-06,smartor_nhfy): -- 任务模板 710 个,能映射到库模板的 663 个(另外 47 个模板 / 879 个选项没有库来源, -- 本脚本不会动它们,需要人工处理); -- 任务题目 6409 道,按题面能对上库题目 6353 道(99.1%); -- 任务选项 16405 个,能对上库选项 16369 个(99.8%)。 -- -- 三个方案,按需要只跑其中一个: -- 方案A(推荐):只把 lib 里标了默认(=2)的选项推到 task,不动 task 已有的其它值 -- → 实测影响 34 行 -- 方案B(完全对齐):lib=2 → 2,lib=1/NULL → 1(不写 NULL) -- → 实测影响 86 行(额外 52 行是把 task 里有、lib 里没有的默认去掉) -- 方案C(严格镜像):连 NULL 一起照抄 -- → 实测影响 10867 行,其中 10782 行会被置成 NULL,通常不建议 -- -- 执行前请先跑第 0 步备份、第 1 步预检。 -- ============================================================================ -- --------------------------------------------------------------------------- -- 0. 备份(只备份会被改动的那几列,整表太大没必要) -- --------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS bak_svy_task_targetoption_dv_20261106 AS SELECT id, taskid, templateID, scriptid, optioncontent, default_value FROM svy_task_template_targetoption WHERE del_flag = '0'; -- 行数应与下面一致(实测 17403 行) SELECT COUNT(*) AS bak_rows FROM bak_svy_task_targetoption_dv_20261106; -- 变更前分布(实测:1=16397,2=1005,4=1) SELECT default_value, COUNT(*) AS cnt FROM svy_task_template_targetoption WHERE del_flag = '0' GROUP BY default_value ORDER BY cnt DESC; -- --------------------------------------------------------------------------- -- 1. 预检:看看 lib 的默认值同步到 task 会改多少行、改成什么 -- --------------------------------------------------------------------------- -- 1.1 汇总(按方案A/B/C 分别预估) SELECT '方案A 只推 lib=2' AS plan, SUM(ld.dv = 2 AND COALESCE(o.default_value, 0) <> 2) AS will_change FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent WHERE o.del_flag = '0' UNION ALL SELECT '方案B 1/2 完全对齐', SUM(COALESCE(o.default_value, 1) <> (CASE WHEN ld.dv = 2 THEN 2 ELSE 1 END)) FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent WHERE o.del_flag = '0' UNION ALL SELECT '方案C 严格镜像(含NULL)', SUM(COALESCE(o.default_value, -1) <> COALESCE(ld.dv, -1)) FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent WHERE o.del_flag = '0'; -- 1.2 逐行差异清单(改动前先看一眼,确认没有不该改的) SELECT o.id AS task_option_id, o.templateid AS task_template, tt.svyname, LEFT(s.script_content, 30) AS question, o.optioncontent, o.default_value AS task_now, ld.dv AS lib_value FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent WHERE o.del_flag = '0' AND COALESCE(o.default_value, 1) <> (CASE WHEN ld.dv = 2 THEN 2 ELSE 1 END) ORDER BY o.templateid, s.id, o.id; -- 1.3 顺带看看哪些 task 选项在库里找不到(题面被改过/新加选项),这些不会被同步 SELECT COUNT(*) AS unmapped_option_rows FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' LEFT JOIN svy_lib_template_script l ON l.svyid = lt.svyid AND l.script_content = s.script_content AND l.del_flag = '0' LEFT JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' AND lo.optioncontent = o.optioncontent WHERE o.del_flag = '0' AND lo.id IS NULL; -- --------------------------------------------------------------------------- -- 2. 方案A(推荐):把库里的默认选项(=2)同步到任务模板选项 -- 实测影响 34 行;不动 task 里已有的 1 / NULL,避免误删任务侧单独配过的默认项 -- (MySQL 多表 UPDATE 不能带 ORDER BY / LIMIT,下面的条件已经能定位到行) -- --------------------------------------------------------------------------- UPDATE svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent SET o.default_value = 2 WHERE o.del_flag = '0' AND ld.dv = 2 AND COALESCE(o.default_value, 0) <> 2; -- --------------------------------------------------------------------------- -- 3. 方案B:和库完全对齐(lib=2 → 2,lib=1/NULL → 1),实测影响 86 行 -- 注意:会把 task 里「有默认、但库里没标默认」的 52 行改成 1 -- --------------------------------------------------------------------------- -- UPDATE svy_task_template_targetoption o -- JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' -- JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' -- JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' -- JOIN ( -- SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv -- FROM svy_lib_template_script l -- JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' -- WHERE l.del_flag = '0' -- GROUP BY l.svyid, l.script_content, lo.optioncontent -- ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent -- SET o.default_value = CASE WHEN ld.dv = 2 THEN 2 ELSE 1 END -- WHERE o.del_flag = '0' -- AND COALESCE(o.default_value, 1) <> (CASE WHEN ld.dv = 2 THEN 2 ELSE 1 END); -- --------------------------------------------------------------------------- -- 4. 方案C:严格镜像库里的值(连 NULL 一起照抄),实测影响 10867 行, -- 其中 10782 行会被置成 NULL(库里这些选项本身没设默认值)。一般不建议。 -- --------------------------------------------------------------------------- -- UPDATE svy_task_template_targetoption o -- JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' -- JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' -- JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' -- JOIN ( -- SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv -- FROM svy_lib_template_script l -- JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' -- WHERE l.del_flag = '0' -- GROUP BY l.svyid, l.script_content, lo.optioncontent -- ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent -- SET o.default_value = ld.dv -- WHERE o.del_flag = '0' -- AND COALESCE(o.default_value, -1) <> COALESCE(ld.dv, -1); -- --------------------------------------------------------------------------- -- 5. 收窄范围示例(只想动某几个任务模板时,在 WHERE 里加条件即可) -- 任务模板 id 来自 svy_task_template.id(= svy_task_template_script.templateid) -- --------------------------------------------------------------------------- -- 5.1 只同步任务模板 514(全院科满意度;实测已一致,改 0 行) -- UPDATE svy_task_template_targetoption o -- JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' -- JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' -- JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' -- JOIN ( -- SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv -- FROM svy_lib_template_script l -- JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' -- WHERE l.del_flag = '0' -- GROUP BY l.svyid, l.script_content, lo.optioncontent -- ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent -- SET o.default_value = 2 -- WHERE o.del_flag = '0' -- AND ld.dv = 2 -- AND COALESCE(o.default_value, 0) <> 2 -- AND s.templateid IN (514); -- 5.2 只同步某个机构下的任务模板(orgid 在两个 option 表上都有) -- AND o.orgid = ' xxx ' -- --------------------------------------------------------------------------- -- 6. 校验 -- --------------------------------------------------------------------------- -- 6.1 改动后分布(方案A 之后应为:1=16363,2=1039,4=1) SELECT default_value, COUNT(*) AS cnt FROM svy_task_template_targetoption WHERE del_flag = '0' GROUP BY default_value ORDER BY cnt DESC; -- 6.2 仍与库不一致的行数(方案A 之后应为 10833,差的都是 lib 侧未设置/为1 的行) SELECT COUNT(*) AS still_diff FROM svy_task_template_targetoption o JOIN svy_task_template_script s ON s.id = o.scriptid AND s.del_flag = '0' JOIN svy_task_template tt ON tt.id = s.templateid AND tt.del_flag = '0' JOIN svy_lib_template lt ON lt.svyid = tt.templateid AND lt.del_flag = '0' JOIN ( SELECT l.svyid, l.script_content, lo.optioncontent, MAX(lo.default_value) AS dv FROM svy_lib_template_script l JOIN svy_lib_template_targetoption lo ON lo.scriptid = l.id AND lo.del_flag = '0' WHERE l.del_flag = '0' GROUP BY l.svyid, l.script_content, lo.optioncontent ) ld ON ld.svyid = lt.svyid AND ld.script_content = s.script_content AND ld.optioncontent = o.optioncontent WHERE o.del_flag = '0' AND COALESCE(o.default_value, 0) <> COALESCE(ld.dv, 0); -- 6.3 每题「默认选项的个数」分布:正常应最多 1 个。 -- 实测跑完方案A 后:0 个=5624 题,1 个=1017 题,2 个=8 题,3 个=2 题 -- (库里本身就有 1 道题挂了 2 个默认项;带 2/3 个默认项的题目属于同步前就存在的问题) SELECT c AS default_options_per_question, COUNT(*) AS questions FROM (SELECT s.id, SUM(o.default_value = 2) c FROM svy_task_template_script s JOIN svy_task_template_targetoption o ON o.scriptid = s.id AND o.del_flag = '0' WHERE s.del_flag = '0' GROUP BY s.id) x GROUP BY c ORDER BY c; -- --------------------------------------------------------------------------- -- 7. 回滚(只把被改过的那几列写回备份值) -- --------------------------------------------------------------------------- -- UPDATE svy_task_template_targetoption o -- JOIN bak_svy_task_targetoption_dv_20261106 b ON b.id = o.id -- SET o.default_value = b.default_value -- WHERE o.del_flag = '0'; -- -- 确认没问题后再删备份表: -- DROP TABLE bak_svy_task_targetoption_dv_20261106;