-- ============================================================================
|
-- 南华附一(nhfy)满意度统计 /smartor/satisfaction/statistics 查不出数据 —— 定位与修复
|
-- 2026-10-21
|
--
|
-- 【请求】POST /prod-api/smartor/satisfaction/statistics
|
-- { "type":2, "startTime":"2026-07-23", "endTime":"2026-10-21",
|
-- "deptcodes":["40003511"], "hospitaldistrictcodes":["40003514"],
|
-- "scriptids":[], "templateid":null }
|
-- 结果:页面一行数据都没有。
|
--
|
-- 【根因】三个问题叠加,任何一个都会让接口返回空:
|
--
|
-- ① 科室/病区被写成 AND(代码 Bug)
|
-- SatisfactionMapper.xml#selectSatisfactionSubtaskTypes
|
-- 原来是「leavehospitaldistrictcode IN(...) AND deptcode IN(...)」两条独立条件。
|
-- 但满意度子任务(type=2 + service_type 6/14/15/16)在南华**只写 deptcode**,
|
-- leavehospitaldistrictcode 全为 NULL(实测 3803 条全部 NULL)→ 两个条件永远不可能同时成立
|
-- → types 查空 → hasVoice / hasQuestionnaire 都 false → 整个接口直接返回空。
|
-- 同一个页面的另外 3 条 SQL(sendCount / FillPersonCountByQuestion / FillStatByMatchedtext)
|
-- 用的都是「科室 OR 病区」,只有这一条写成了 AND,属于重构时漏改。
|
--
|
-- ② 时间过滤列 visit_time 全为 NULL(数据问题)
|
-- 统计的 4 条 SQL 都用 `visit_time >= startTime AND visit_time < endTime+1d`,
|
-- 而南华的满意度子任务 visit_time **3803 条全部为 NULL**(今天的也在写 NULL)
|
-- → 即使 ① 修好,日期条件仍然把数据全部排除。
|
--
|
-- ③ 问卷题目没有挂到「满意度(myd)」分类(配置问题)
|
-- 统计页的题目清单来自 svy_lib_script_category 中 type 含 myd 的分类 →
|
-- svy_lib_template_script.categoryid IN (这些分类)。
|
-- 南华 myd 分类只有 1 个(id=62,name=满意度),里面是 6 道老题(svyid 51/97/102/103/154/156,
|
-- 属于其它问卷模板),而真正在填的 19 道题(svyid=200 / 模板 514)**categoryid 全是 NULL**
|
-- → 即使 ① ② 修好,页面也只会列出那 6 道没有数据的老题。
|
--
|
-- 【已做的修复】
|
-- 代码(需发版):
|
-- SatisfactionMapper.xml
|
-- · selectSatisfactionSubtaskTypes:科室/病区改为 OR,与其余三条统计 SQL 口径一致
|
-- · 4 条统计 SQL 的时间条件改为
|
-- IFNULL(visit_time, IFNULL(finishtime, create_time))(visit_time 为空时按完成/创建时间兜底)
|
-- 数据(已执行,本脚本记录):
|
-- · 把模板 200 的 19 道题挂到满意度分类 id=62(19 行)
|
-- 备份表:bak_svy_lts_cat_20261021
|
--
|
-- 【修复后实测(2026-10-21,条件同截图)】
|
-- types = ['2'];发送人数 387;19 道题逐题答题人数 380(答题率 98.2%)
|
--
|
-- 【回滚】
|
-- UPDATE svy_lib_template_script t
|
-- JOIN bak_svy_lts_cat_20261021 b ON b.id = t.id
|
-- SET t.categoryid = b.categoryid;
|
-- ============================================================================
|
|
|
-- ----------------------------------------------------------------------------
|
-- 【0】故障复现(修复前这三条要能说明问题)
|
-- ----------------------------------------------------------------------------
|
-- ① 类型探测:修复前返回 0 行
|
SELECT DISTINCT type
|
FROM service_subtask
|
WHERE del_flag = 0
|
AND leavehospitaldistrictcode IN ('40003514')
|
AND deptcode IN ('40003511') -- 与上一行是 AND,故永远不成立
|
AND service_type IN ('6', '14', '15', '16')
|
AND visit_time >= '2026-07-23'
|
AND visit_time < date_add('2026-10-21', interval 1 day);
|
|
-- ② 满意度子任务的时间/科室字段现状
|
SELECT COUNT(*) AS rows_total,
|
SUM(visit_time IS NULL) AS visit_time_null,
|
SUM(leavehospitaldistrictcode IS NULL) AS district_null,
|
SUM(deptcode IS NOT NULL) AS has_deptcode
|
FROM service_subtask
|
WHERE del_flag = 0 AND type = '2' AND service_type IN ('6', '14', '15', '16');
|
|
-- ③ 修复前 myd 分类里只有 6 道老题(svyid 不含 200)
|
SELECT COUNT(*) AS myd_questions, GROUP_CONCAT(DISTINCT svyid) AS svyids
|
FROM svy_lib_template_script
|
WHERE categoryid = 62 AND del_flag = 0;
|
|
|
-- ----------------------------------------------------------------------------
|
-- 【1】已执行:把模板 200 的 19 道题挂到满意度分类 62
|
-- ----------------------------------------------------------------------------
|
-- DROP TABLE IF EXISTS bak_svy_lts_cat_20261021;
|
-- CREATE TABLE bak_svy_lts_cat_20261021 AS
|
-- SELECT id, svyid, categoryid, script_content
|
-- FROM svy_lib_template_script
|
-- WHERE svyid = 200 AND categoryid IS NULL AND del_flag = 0; -- 19 行
|
--
|
-- UPDATE svy_lib_template_script
|
-- SET categoryid = 62
|
-- WHERE svyid = 200 AND categoryid IS NULL AND del_flag = 0; -- 19 行
|
|
|
-- ----------------------------------------------------------------------------
|
-- 【2】修复后校验:页面上每道题的 发送人数 / 答题人数
|
-- 预期:19 道 svyid=200 的题都是 387 / 380;6 道老题 0 / 0
|
-- ----------------------------------------------------------------------------
|
SELECT s.id AS script_id, s.svyid,
|
LEFT(s.script_content, 18) AS question,
|
(SELECT COUNT(DISTINCT ss.id)
|
FROM service_subtask ss
|
WHERE ss.del_flag = 0 AND ss.type = '2' AND ss.libtemplateid = s.svyid
|
AND ss.service_type IN ('6', '14', '15', '16')
|
AND IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) >= '2026-07-23 00:00:00'
|
AND IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) < date_add('2026-10-21 00:00:00', interval 1 day)
|
AND (ss.leavehospitaldistrictcode IN ('40003514') OR ss.deptcode IN ('40003511'))) AS send_person,
|
(SELECT COUNT(DISTINCT ss.id)
|
FROM service_subtask ss
|
JOIN service_subtask_detail d ON d.sub_id = ss.id AND d.del_flag = 0
|
WHERE ss.del_flag = 0 AND ss.type = '2' AND ss.libtemplateid = s.svyid
|
AND ss.service_type IN ('6', '14', '15', '16')
|
AND IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) >= '2026-07-23 00:00:00'
|
AND IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)) < date_add('2026-10-21 00:00:00', interval 1 day)
|
AND (ss.leavehospitaldistrictcode IN ('40003514') OR ss.deptcode IN ('40003511'))
|
AND d.questiontext = s.script_content) AS answer_person
|
FROM svy_lib_template_script s
|
WHERE s.categoryid = 62 AND s.del_flag = 0
|
ORDER BY s.svyid, s.id;
|
|
|
-- ============================================================================
|
-- 【后续建议(可选)】
|
-- 1) visit_time 补数据(让所有按 visit_time 过滤的报表都能查到满意度数据,
|
-- 也能走索引;代码里的 IFNULL 兜底是保险,不等于数据本身正确):
|
-- UPDATE service_subtask
|
-- SET visit_time = IFNULL(finishtime, create_time)
|
-- WHERE del_flag = 0 AND type = '2' AND service_type IN ('6','14','15','16')
|
-- AND visit_time IS NULL; -- 实测 3803 行
|
-- ⚠️ 与「随访完成时间」口径相关的看板会受影响,建议先确认业务口径再执行。
|
--
|
-- 2) 分类里那 6 道老题(svyid 51/97/102/103/154/156)现在会以 0/0 显示——
|
-- 它们属于其它问卷模板、不参与满意度统计但被挂在了 myd 分类上。
|
-- 想让页面只显示 19 道真题的话,把它们从分类里摘掉即可:
|
-- UPDATE svy_lib_template_script SET categoryid = NULL
|
-- WHERE categoryid = 62 AND svyid <> 200 AND del_flag = 0; -- 6 行(先备份)
|
--
|
-- 3) 前端请求里带了 scriptids: [] 和 templateid: null,
|
-- 但后端 PatSatisfactionReqVO 没有 scriptids 字段(会被忽略)、statistics 也不用 templateid,
|
-- 如果要按题目/模板筛选,需要前后端一起补。
|
-- ============================================================================
|