如何使用Knex按月-日区间查询所有年份的生日数据
Knex跨月生日区间查询解决方案
你的现有代码逻辑只适用于同月份内的日期区间查询,当区间跨月(比如3月28日到4月3日)时,会因为同时要求「日>=28」和「日<=3」导致没有匹配结果——单个日期不可能同时满足这两个条件。
要实现跨年份的月-日区间查询,可参考以下两种解决方案:
方案一:分跨月/同月逻辑处理
const query = this.db("user_table"); // 计算起始和结束日期的月、日(确保两位格式) const startDate = sub(new Date(), { days: 7 }); const endDate = new Date(); const monthIni = format(startDate, "MM"); const dayIni = format(startDate, "DD"); const monthEnd = format(endDate, "MM"); const dayEnd = format(endDate, "DD"); if (monthIni === monthEnd) { // 区间在同一个月内,直接匹配月相等且日在区间内 query.whereRaw( "EXTRACT(MONTH FROM user_table.birth) = ? AND EXTRACT(DAY FROM user_table.birth) BETWEEN ? AND ?", [monthIni, dayIni, dayEnd] ); } else { // 区间跨月,匹配「起始月的起始日之后」或「结束月的结束日之前」 query.where((builder) => { builder.whereRaw( "EXTRACT(MONTH FROM user_table.birth) = ? AND EXTRACT(DAY FROM user_table.birth) >= ?", [monthIni, dayIni] ).orWhereRaw( "EXTRACT(MONTH FROM user_table.birth) = ? AND EXTRACT(DAY FROM user_table.birth) <= ?", [monthEnd, dayEnd] ); }); }
方案二:转换为月-日字符串比较(更简洁)
如果你的数据库支持日期格式化函数,可以直接将生日转换为MM-DD格式的字符串,再做区间比较(不同数据库对应函数不同):
- PostgreSQL 使用
TO_CHAR(birth, 'MM-DD') - MySQL 使用
DATE_FORMAT(birth, '%m-%d') - SQL Server 使用
FORMAT(birth, 'MM-dd')
示例(以PostgreSQL为例):
const query = this.db("user_table"); const startDate = sub(new Date(), { days: 7 }); const endDate = new Date(); const startMonthDay = format(startDate, "MM-DD"); const endMonthDay = format(endDate, "MM-DD"); query.whereRaw( "TO_CHAR(user_table.birth, 'MM-DD') BETWEEN ? AND ?", [startMonthDay, endMonthDay] );
这种方法无需判断是否跨月,字符串比较会自动处理跨月场景(比如03-28 <= 04-03逻辑成立)。
内容的提问来源于stack exchange,提问作者Ezequiel Tavares
相关产品推荐
相关产品推荐

