MySQL如何正确查询指定日期范围内的有效租赁订单
问题说明
现有存储租赁记录的rental数据表,包含以下字段:
id:租赁记录唯一标识date_from:租赁起始日期date_to:租赁结束日期
需求是检索指定日期区间内所有生效的租赁记录,用于库存盘点。
初始使用的查询语句如下:
SELECT * FROM 'rental' WHERE ('date_from' BETWEEN '2022-06-15' AND '2022-06-17') OR ('date_to' BETWEEN '2022-06-15' AND '2022-06-17');
该语句存在两个明显问题:
- 语法错误:给表名、字段名错误添加了单引号,单引号包裹的内容会被数据库识别为字符串常量,而非表/字段标识符,部分数据库环境下会直接报错
- 逻辑漏洞:只能匹配租赁起始/结束时间落在查询区间内的记录,会漏掉租赁开始早于查询起始日、租赁结束晚于查询结束日,完全覆盖整个查询区间的租赁记录,导致盘点结果不准。
核心判断逻辑
要找出所有和查询区间存在交集的租赁记录,不需要枚举所有重叠场景,只需要记住时间区间重叠的充要条件:
租赁区间的起始时间 不晚于 查询区间的结束时间,且租赁区间的结束时间 不早于 查询区间的起始时间
这个规则可以覆盖所有重叠场景,包括:
- 租赁起止时间完全落在查询区间内
- 租赁起始时间在查询区间内,结束时间晚于查询结束日
- 租赁结束时间在查询区间内,起始时间早于查询起始日
- 租赁区间完全覆盖整个查询区间(即原语句漏掉的场景)
正确SQL写法
以查询2022-06-15到2022-06-17区间内的有效租赁记录为例,正向判断的写法如下:
SELECT * FROM rental WHERE date_from <= '2022-06-17' AND date_to >= '2022-06-15';
如果觉得正向逻辑不好记忆,也可以用排除法,先筛掉完全不重叠的记录再取反,逻辑和上面完全等价:
SELECT * FROM rental WHERE NOT ( date_to < '2022-06-15' -- 租赁在查询区间开始前就已结束,无交集 OR date_from > '2022-06-17' -- 租赁在查询区间结束后才开始,无交集 );
注意:如果你的表名、字段名是数据库保留字,需要转义时请使用对应数据库支持的标识符转义符,比如MySQL用反引号
`、PostgreSQL用双引号",不要用单引号。
内容的提问来源于stack exchange,提问作者VkVk
相关产品推荐
相关产品推荐

