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

如何查询无时间冲突的可预订车辆?现有SQL查询无结果排查

查询无时间冲突的可预订车辆解决方案

你原来的查询没有返回结果的核心原因是LEFT JOIN后处理NULL值的逻辑错误:

  • 对于没有任何预订记录的车辆(OPEL、MERCEDES、AUDI),LEFT JOIN后b.booking_range为NULL。在PostgreSQL中,任何与NULL的逻辑运算(比如&&重叠判断)结果都是NULL,而WHERE子句只会保留结果为TRUE的行,这些车辆因此被过滤。
  • 对于有预订的BMW,其预订区间与指定时间范围重叠,NOT (...)的结果为FALSE,同样被WHERE子句过滤。
    最终所有行都被排除,所以没有返回数据。

方法一:使用NOT EXISTS(推荐,逻辑清晰且性能优)

这种方式直接检查每辆车是否不存在与指定时间冲突的预订记录,是最直观的解决方案:

SELECT c.id AS car_id, c.name
FROM cars c
WHERE NOT EXISTS (
    SELECT 1
    FROM booking b
    WHERE b.car_id = c.id
      -- 判断预订区间与目标时间是否重叠
      AND b.booking_range && tsrange('2023-04-11', '2023-04-15', '()')
);

逻辑说明:

  • NOT EXISTS子查询会针对每辆车,检查是否存在冲突的预订。如果子查询返回空(无冲突预订),则该车辆会被保留。
  • 对于从未被预订的车辆,子查询自然返回空,因此会被选中。

方法二:修正LEFT JOIN + GROUP BY + HAVING

如果坚持使用LEFT JOIN,可以通过分组统计冲突预订的数量来实现:

SELECT c.id AS car_id, c.name
FROM cars c
LEFT JOIN booking b 
  ON b.car_id = c.id
GROUP BY c.id, c.name
HAVING COUNT(
    CASE 
      WHEN b.booking_range && tsrange('2023-04-11', '2023-04-15', '()') 
      THEN 1 
    END
) = 0;

逻辑说明:

  • 先通过LEFT JOIN关联车辆和其所有预订记录。
  • 使用COUNT(CASE ...)统计该车辆中与目标时间冲突的预订数量。
  • HAVING COUNT(...) = 0确保该车辆没有任何冲突的预订,符合可预订条件。

测试验证

针对你的测试数据,执行上述任意查询,都会返回以下结果:

car_idname
2OPEL
3MERCEDES
4AUDI

这符合预期:BMW因存在时间冲突被排除,其余无预订的车辆均被选中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:32:45