You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多对多关联子查询问题:筛选有效可用时段

解决可用时段筛选的SQL查询问题

嘿,我来帮你搞定这个可用时段筛选的问题!你之前的查询之所以会显示所有可用时段,大概率是没处理好**“该时段至少有一位心理学家拥有它,且这位心理学家没把它加入已占用列表”**这个核心条件。

核心思路

我们要找的时段需要满足:存在至少一位心理学家,其名下的这个可用时段没有出现在自己的已占用时段列表中。换句话说,要排除掉那些「所有拥有该时段的心理学家都把它占用了」的时段(比如示例里的2am,只有psy2有这个时段但他已经占用了,所以要排除)。

假设的表结构

先明确下我们用到的两张表结构(如果你的表字段名不同,替换成对应名称即可):

  • availabilities:存储心理学家的可用时段,字段包括 psychologist_id(心理学家ID)、time_slot(时段)
  • taken_availabilities:存储心理学家的已占用时段,字段包括 psychologist_id、time_slot

方案一:使用LEFT JOIN + 分组筛选

这种方法通过关联两张表,统计每个时段的总可用次数和被占用次数,筛选出被占用次数小于总可用次数的时段(说明至少有一个心理学家的该时段未被占用):

SELECT a.time_slot
FROM availabilities a
LEFT JOIN taken_availabilities t
  ON a.psychologist_id = t.psychologist_id
  AND a.time_slot = t.time_slot
GROUP BY a.time_slot
HAVING COUNT(t.time_slot) < COUNT(a.time_slot);

逻辑解释

  • LEFT JOIN会保留所有可用时段,若某时段未被对应心理学家占用,t.time_slot 会是NULL
  • 分组后,COUNT(t.time_slot) 统计该时段被占用的次数,COUNT(a.time_slot) 统计该时段的总可用次数
  • 当被占用次数小于总可用次数时,说明至少有一个心理学家的这个时段没被占用,符合我们的需求

方案二:使用NOT EXISTS + 去重

这种方法直接筛选出「心理学家的可用时段未被自己占用」的记录,再通过去重得到最终的时段列表:

SELECT DISTINCT a.time_slot
FROM availabilities a
WHERE NOT EXISTS (
  SELECT 1
  FROM taken_availabilities t
  WHERE t.psychologist_id = a.psychologist_id
    AND t.time_slot = a.time_slot
);

逻辑解释

  • NOT EXISTS 子查询用来判断当前心理学家的这个可用时段是否存在于他的已占用列表中
  • 只保留那些未被占用的可用时段,最后用DISTINCT去重,得到唯一的有效时段

示例验证

用你给出的示例数据测试:

  • availabilities 包含:psy1的1am、psy2的2am、psy2的3am
  • taken_availabilities 包含:psy2的2am

两种查询都会返回 1am 和 3am,完美符合预期!

内容的提问来源于stack exchange,提问作者Martin Volpe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:21:10