MySQL患者30天内再入院查询:重复记录问题排查与优化
问题原因分析
你的查询出现重复记录,核心原因是左连接条件匹配了多条历史出院记录:
当某个患者的当前入院记录,和他之前不止一次的出院记录都满足「间隔1-29天」时,左连接会把当前记录和每一条符合条件的历史记录做一次关联,导致同一个visit_no被重复输出。比如患者第3次入院,若和第1、2次出院的间隔都在30天内,这条visit_no就会被输出2次。
正确查询方案
要解决这个问题,应该使用窗口函数LAG(),它能精准获取每个患者最近一次的出院记录,而不是所有符合间隔条件的记录,这样每个visit_no只会对应一条结果。
完整SQL语句(考虑日期+时间的精确计算)
SELECT visit_no, mr_no, admit_date, admit_time, dischg_date, dischg_time, -- 判断是否30天内再入院 CASE WHEN DATEDIFF( STR_TO_DATE(CONCAT(admit_date, ' ', admit_time), '%Y-%m-%d %H:%i:%s'), prev_dischg_datetime ) BETWEEN 1 AND 29 THEN 'Y' ELSE 'N' END AS Readmit, -- 计算间隔天数 DATEDIFF( STR_TO_DATE(CONCAT(admit_date, ' ', admit_time), '%Y-%m-%d %H:%i:%s'), prev_dischg_datetime ) AS Days_Between FROM ( SELECT *, -- 获取当前患者上一次出院的完整datetime LAG(STR_TO_DATE(CONCAT(dischg_date, ' ', dischg_time), '%Y-%m-%d %H:%i:%s')) OVER (PARTITION BY mr_no ORDER BY STR_TO_DATE(CONCAT(admit_date, ' ', admit_time), '%Y-%m-%d %H:%i:%s')) AS prev_dischg_datetime FROM chmadmtr WHERE mr_no = '508' ) AS t ORDER BY STR_TO_DATE(CONCAT(admit_date, ' ', admit_time), '%Y-%m-%d %H:%i:%s') ASC;
关键说明
LAG()窗口函数:PARTITION BY mr_no:按患者分组,确保只在同一个患者的记录间查找前次出院ORDER BY ...:按入院的完整时间排序,保证取到的是最近的一次出院记录
- 日期时间合并:用
STR_TO_DATE(CONCAT(admit_date, ' ', admit_time), ...)把日期和时间字段合并为datetime类型,避免只按日期计算导致的误差(比如前一天23点出院,当天1点入院,间隔实际不足1天) - 第一次入院处理:第一次入院没有前次出院记录,
prev_dischg_datetime为NULL,此时Days_Between为NULL,Readmit自动为'N',符合业务逻辑
如果你的日期字段已经是datetime类型(不需要拆分日期和时间),可以简化SQL:
SELECT visit_no, mr_no, admit_date, dischg_date, CASE WHEN DATEDIFF(admit_date, prev_dischg_date) BETWEEN 1 AND 29 THEN 'Y' ELSE 'N' END AS Readmit, DATEDIFF(admit_date, prev_dischg_date) AS Days_Between FROM ( SELECT *, LAG(dischg_date) OVER (PARTITION BY mr_no ORDER BY admit_date) AS prev_dischg_date FROM chmadmtr WHERE mr_no = '508' ) AS t ORDER BY admit_date ASC;
内容的提问来源于stack exchange,提问作者oscarmnz8
相关产品推荐
相关产品推荐

