如何为每日最后一条记录查询添加指定时间段筛选功能?
问题分析与解决方案
你的问题出在筛选条件的位置错误——你把DATE(created_at) BETWEEN ...写在了ORDER BY子句后面,这不仅不符合SQL语法规范,也根本起不到筛选时间段的作用,反而会导致排序逻辑异常。
修正后的代码(基础版)
把筛选条件放在WHERE子句中,同时给子查询也加上时间段过滤(减少分组计算的数据量,提升查询效率):
SELECT t1.id, t1.created_at FROM waterstation.waterstation_lifecycle_history t1 INNER JOIN ( SELECT DATE(created_at) AS createdAt, MAX(created_at) AS maxcreatedAt FROM waterstation.waterstation_lifecycle_history -- 子查询先过滤目标时间段,缩小计算范围 WHERE DATE(created_at) BETWEEN DATE('2022-09-13') AND DATE('2022-09-27') GROUP BY DATE(created_at) ) t2 ON t2.createdAt = DATE(t1.created_at) AND t2.maxcreatedAt = t1.created_at -- 主查询再次过滤,确保结果严谨 WHERE DATE(t1.created_at) BETWEEN DATE('2022-09-13') AND DATE('2022-09-27') ORDER BY t1.created_at;
原代码无效的核心原因
SQL的执行顺序是:FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。你把筛选条件放在ORDER BY后,相当于用布尔值(DATE(...) BETWEEN ...的返回结果是true/false)来排序,完全偏离了筛选数据的目的。
可选优化:用窗口函数简化逻辑
如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL等),可以用更简洁的写法实现需求:
SELECT id, created_at FROM ( SELECT id, created_at, ROW_NUMBER() OVER (PARTITION BY DATE(created_at) ORDER BY created_at DESC) AS rn FROM waterstation.waterstation_lifecycle_history WHERE DATE(created_at) BETWEEN DATE('2022-09-13') AND DATE('2022-09-27') ) t WHERE rn = 1 ORDER BY created_at;
这种写法逻辑更直观,不需要额外的JOIN操作,同样能精准获取指定时间段内每日的最后一条记录。
内容的提问来源于stack exchange,提问作者pat des pat
相关产品推荐
相关产品推荐

