SQL一对多关联下查询指定日期未预约产品的左连接问题
问题根因
- 左关联后无预约的产品对应的
reservation表所有字段均为NULL,你将预约时间的过滤放在WHERE子句中,NULL和任意值做比较都会返回UNKNOWN,会被WHERE条件直接过滤,因此无预约的产品不会出现在结果中。 - 原有时间范围判断逻辑有误,没有正确识别预约和目标时间段的重叠关系,也会导致结果不符合预期。
解决方案
方案1:将时间过滤移到LEFT JOIN的ON子句中
把预约的时间过滤条件从WHERE移到LEFT JOIN reservation的ON条件里,仅关联和目标时间段重叠的预约,再过滤没有匹配到预约的产品即可,修改后SQL如下:
SELECT p.idProduct, p.name, p.description, p.latitude, p.longitude, p.address, p.qualification, p.favourite,p.idCategory,p.idCity, p.rules, p.health, p.politics FROM product p LEFT JOIN city c ON c.idCity = p.idCity LEFT JOIN reservation r ON r.idProduct = p.idProduct -- 仅关联和目标时间段[2021-11-20, 2021-11-28]重叠的预约 AND r.startDate <= '2021-11-28' AND r.endDate >= '2021-11-20' WHERE p.idCity = 1 -- 没有匹配到重叠预约的产品即为符合要求的产品 AND r.idReservation IS NULL;
方案2:使用NOT EXISTS实现(逻辑更直观)
直接用NOT EXISTS判断产品不存在和目标时间段重叠的预约即可,天然包含无任何预约的产品,SQL如下:
SELECT p.idProduct, p.name, p.description, p.latitude, p.longitude, p.address, p.qualification, p.favourite,p.idCategory,p.idCity, p.rules, p.health, p.politics FROM product p WHERE p.idCity = 1 AND NOT EXISTS ( SELECT 1 FROM reservation r WHERE r.idProduct = p.idProduct AND r.startDate <= '2021-11-28' AND r.endDate >= '2021-11-20' )
注:判断两个时间段重叠的通用逻辑为「A的开始时间小于等于B的结束时间,且A的结束时间大于等于B的开始时间」,可以覆盖所有重叠场景。
内容的提问来源于stack exchange,提问作者Laura Nieto
相关产品推荐
相关产品推荐

