Commit c37f0e41 by luoqi

verify-recall: FN 分解加 §E 剔除层(智齿/先天/正畸减数)+ 改 CASE 归桶

§E 三条剔除(已落地 scenario)之前会被扫描器虚报成 truly_unexplained;补 x_thirdmolar/
x_congenital/x_orthoextract 三 flag,FN 按首个命中归桶,truly_unexplained 才准。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
parent 0940c635
...@@ -83,6 +83,12 @@ GROUP BY d.patient_id, c.code, c.sub, c.resolver, c.complaints, c.drop_decid, tk ...@@ -83,6 +83,12 @@ GROUP BY d.patient_id, c.code, c.sub, c.resolver, c.complaints, c.drop_decid, tk
DELETE FROM vt_diag WHERE dx_at > now() - (cooldown||' days')::interval; DELETE FROM vt_diag WHERE dx_at > now() - (cooldown||' days')::interval;
CREATE INDEX ON vt_diag(patient_id, tooth); ANALYZE vt_diag; CREATE INDEX ON vt_diag(patient_id, tooth); ANALYZE vt_diag;
-- §E 正畸语境患者(K07 诊断 或 正畸治疗)— 给 x_orthoextract 用
CREATE TEMP TABLE vt_ortho_pt AS
SELECT DISTINCT patient_id FROM patient_facts WHERE status='active' AND type='diagnosis_record' AND content->>'code'='K07'
UNION SELECT DISTINCT patient_id FROM patient_facts WHERE type='treatment_record' AND content->>'category'='orthodontic';
CREATE INDEX ON vt_ortho_pt(patient_id); ANALYZE vt_ortho_pt;
-- ── 分类(EXISTS 全打索引临时表,秒级)── -- ── 分类(EXISTS 全打索引临时表,秒级)──
CREATE TEMP TABLE vt_final AS CREATE TEMP TABLE vt_final AS
SELECT d.patient_id, d.code, d.sub, d.tooth, d.dx_at, d.name_zh, SELECT d.patient_id, d.code, d.sub, d.tooth, d.dx_at, d.name_zh,
...@@ -93,7 +99,12 @@ SELECT d.patient_id, d.code, d.sub, d.tooth, d.dx_at, d.name_zh, ...@@ -93,7 +99,12 @@ SELECT d.patient_id, d.code, d.sub, d.tooth, d.dx_at, d.name_zh,
(cardinality(d.complaints)>0 AND EXISTS(SELECT 1 FROM vt_appt a WHERE a.patient_id=d.patient_id AND a.compl=ANY(d.complaints) AND a.appt_at>=d.dx_at)) AS x_appt, (cardinality(d.complaints)>0 AND EXISTS(SELECT 1 FROM vt_appt a WHERE a.patient_id=d.patient_id AND a.compl=ANY(d.complaints) AND a.appt_at>=d.dx_at)) AS x_appt,
(d.name_zh IN('废用牙','无功能牙')) AS x_inelig, (d.name_zh IN('废用牙','无功能牙')) AS x_inelig,
(d.drop_decid AND d.tooth ~ '^[5-8][1-5]$') AS x_decid, (d.drop_decid AND d.tooth ~ '^[5-8][1-5]$') AS x_decid,
EXISTS(SELECT 1 FROM vt_struct s WHERE s.patient_id=d.patient_id AND s.tooth=d.tooth AND s.code<>d.code AND s.at>=d.dx_at) AS x_superseded EXISTS(SELECT 1 FROM vt_struct s WHERE s.patient_id=d.patient_id AND s.tooth=d.tooth AND s.code<>d.code AND s.at>=d.dx_at) AS x_superseded,
-- §E 三条剔除(仅 K08,跟 scenario 代码 missing_tooth 对齐):智齿位 / 先天 / 正畸减数位
(d.code='K08' AND d.tooth ~ '^[1-4]8$') AS x_thirdmolar,
(d.code='K08' AND COALESCE(d.name_zh,'') LIKE '%先天%') AS x_congenital,
(d.code='K08' AND d.patient_id IN (SELECT patient_id FROM vt_ortho_pt)
AND EXISTS(SELECT 1 FROM vt_treat t WHERE t.patient_id=d.patient_id AND t.tooth=d.tooth AND t.cat='surgical')) AS x_orthoextract
FROM vt_diag d; FROM vt_diag d;
ANALYZE vt_final; ANALYZE vt_final;
...@@ -118,19 +129,23 @@ FROM vt_final GROUP BY 1,2 ORDER BY 1,2; ...@@ -118,19 +129,23 @@ FROM vt_final GROUP BY 1,2 ORDER BY 1,2;
\echo '════════ §C2 FP(已治却召)样例 ════════' \echo '════════ §C2 FP(已治却召)样例 ════════'
SELECT substr(patient_id::text,1,8) pid, code, tooth, dx_at::date, name_zh FROM vt_final WHERE resolved AND recalled LIMIT 15; SELECT substr(patient_id::text,1,8) pid, code, tooth, dx_at::date, name_zh FROM vt_final WHERE resolved AND recalled LIMIT 15;
\echo '════════ §C3 FN 逐层解释 → 真·无法解释 ════════' \echo '════════ §C3 FN 逐层解释 → 真·无法解释(按首个命中归桶)════════'
SELECT count(*) AS fn_total, CREATE TEMP VIEW vt_fn AS
count(*) FILTER (WHERE x_future) AS e_future_appt, SELECT *,
count(*) FILTER (WHERE NOT x_future AND x_recent) AS e_recent_visit, CASE
count(*) FILTER (WHERE NOT x_future AND NOT x_recent AND x_appt) AS e_appt_complaint, WHEN x_future THEN '1_未来预约⑤b'
count(*) FILTER (WHERE NOT x_future AND NOT x_recent AND NOT x_appt AND (x_inelig OR x_decid)) AS e_inelig_decid, WHEN x_recent THEN '2_近期到诊⑤f'
count(*) FILTER (WHERE NOT x_future AND NOT x_recent AND NOT x_appt AND NOT x_inelig AND NOT x_decid AND x_superseded) AS e_superseded, WHEN x_appt THEN '3_预约科目⑤d'
count(*) FILTER (WHERE NOT x_future AND NOT x_recent AND NOT x_appt AND NOT x_inelig AND NOT x_decid AND NOT x_superseded) AS truly_unexplained WHEN x_inelig OR x_decid THEN '4_废用牙/乳牙'
WHEN x_thirdmolar OR x_congenital OR x_orthoextract THEN '5_§E剔除(智齿/先天/正畸减数)'
WHEN x_superseded THEN '6_同牙更晚诊断取代'
ELSE '9_真·无法解释'
END AS bucket
FROM vt_final WHERE NOT resolved AND NOT recalled; FROM vt_final WHERE NOT resolved AND NOT recalled;
SELECT bucket, count(*) FROM vt_fn GROUP BY bucket ORDER BY bucket;
\echo '---- 真·无法解释 FN 样例 ----' \echo '---- 真·无法解释 FN 样例 ----'
SELECT code, substr(patient_id::text,1,8) pid, tooth, dx_at::date, name_zh FROM vt_final SELECT code, substr(patient_id::text,1,8) pid, tooth, dx_at::date, name_zh
WHERE NOT resolved AND NOT recalled AND NOT x_future AND NOT x_recent AND NOT x_appt AND NOT x_inelig AND NOT x_decid AND NOT x_superseded FROM vt_fn WHERE bucket='9_真·无法解释' ORDER BY code LIMIT 30;
ORDER BY code LIMIT 30;
\echo '════════ §D 全口码 治疗后复发被压(excludeIfEverTreated)════════' \echo '════════ §D 全口码 治疗后复发被压(excludeIfEverTreated)════════'
WITH tx AS (SELECT patient_id, content->>'category' cat, max(occurred_at) last_tx FROM patient_facts WITH tx AS (SELECT patient_id, content->>'category' cat, max(occurred_at) last_tx FROM patient_facts
...@@ -150,9 +165,6 @@ WHERE p.active AND NOT pp.do_not_contact AND NOT pp.deceased ...@@ -150,9 +165,6 @@ WHERE p.active AND NOT pp.do_not_contact AND NOT pp.deceased
GROUP BY d.code; GROUP BY d.code;
\echo '════════ §E K08 正畸语境 FP 上界(召缺牙→种植 且 有K07诊断/正畸治疗)════════' \echo '════════ §E K08 正畸语境 FP 上界(召缺牙→种植 且 有K07诊断/正畸治疗)════════'
CREATE TEMP TABLE vt_ortho_pt AS -- vt_ortho_pt 已在 vt_final 前建好(给 x_orthoextract 用),此处直接复用
SELECT DISTINCT patient_id FROM patient_facts WHERE status='active' AND type='diagnosis_record' AND content->>'code'='K07'
UNION SELECT DISTINCT patient_id FROM patient_facts WHERE type='treatment_record' AND content->>'category'='orthodontic';
CREATE INDEX ON vt_ortho_pt(patient_id); ANALYZE vt_ortho_pt;
SELECT count(DISTINCT f.patient_id) AS k08_ortho_ctx_patients SELECT count(DISTINCT f.patient_id) AS k08_ortho_ctx_patients
FROM vt_final f WHERE f.code='K08' AND f.recalled AND f.patient_id IN (SELECT patient_id FROM vt_ortho_pt); FROM vt_final f WHERE f.code='K08' AND f.recalled AND f.patient_id IN (SELECT patient_id FROM vt_ortho_pt);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment