SQL技术问询:如何从Calls表排除每个患者的最新预约通话记录
解决思路:获取每个患者的非最新通话记录
嘿,这个需求其实很好解决,咱们有两种常用的SQL方案,刚好能覆盖你的需求——既过滤掉每个患者的最新通话,又自动排除只有一次通话的患者:
方案1:用窗口函数(现代SQL首选)
这是最直观的写法,适合支持窗口函数的数据库(比如MySQL 8+、PostgreSQL、SQL Server等):
SELECT c.* FROM ( SELECT *, -- 按患者分组,通话时间倒序排序,最新的通话标记为1 ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY call_date DESC) AS call_rank FROM Calls ) c -- 只保留排名大于1的,也就是非最新的通话 WHERE c.call_rank > 1;
逻辑说明:
PARTITION BY patient_id:把数据按患者ID分组,每组单独处理ORDER BY call_date DESC:每组内按通话时间从晚到早排序,最新的通话排第1位call_rank > 1:直接筛选出每组里除了最新之外的所有通话,同时自动排除了只有1次通话的患者(因为他们的call_rank只有1,会被过滤掉)
如果你的表是用自增的call_id来判断通话新旧(比如call_id越大越新),把call_date DESC换成call_id DESC就行。
方案2:用子查询+关联查询
如果你的数据库不支持窗口函数(比如老版本MySQL),可以用这种传统写法:
SELECT c.* FROM Calls c -- 关联子查询,找出每个有多次通话患者的最新通话时间 JOIN ( SELECT patient_id, MAX(call_date) AS latest_call_time FROM Calls GROUP BY patient_id -- 先过滤掉只有1次通话的患者 HAVING COUNT(*) > 1 ) latest_calls ON c.patient_id = latest_calls.patient_id -- 筛选出通话时间早于该患者最新时间的记录 WHERE c.call_date < latest_calls.latest_call_time;
逻辑说明:
- 子查询先统计每个患者的通话次数,只保留有多次通话的,同时找出他们的最新通话时间
- 主表和子查询通过患者ID关联,筛选出所有早于最新时间的通话记录,也就是非最新的那些
两种方案都能完美满足你的需求,选哪种看你的数据库版本和个人习惯就行~
内容的提问来源于stack exchange,提问作者Gino Cortes
相关产品推荐
相关产品推荐

