SQL需求:按距离当前时间最近的生日/入职纪念日排序员工列表
解决方案
完整修改后的SQL
SELECT users.*, -- 计算最近的目标日期(生日/入职纪念日) CASE WHEN UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(YEAR(NOW()), ' ', DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), '%m %d')), '%Y %m %d')) >= UNIX_TIMESTAMP(NOW()) THEN STR_TO_DATE(CONCAT(YEAR(NOW()), ' ', DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), '%m %d')), '%Y %m %d') ELSE STR_TO_DATE(CONCAT(YEAR(NOW()) + 1, ' ', DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), '%m %d')), '%Y %m %d') END AS target_date FROM {prefix}usermeta as usermeta JOIN {prefix}users as users ON users.ID = usermeta.user_id WHERE (usermeta.meta_key = "foedselsdag" OR usermeta.meta_key = "jubilaeum") AND ( (UNIX_TIMESTAMP(STR_TO_DATE(CONCAT("%format_date_string|Y|now%", " ", DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), "%m %d")), "%Y %m %d")) < %str_to_time|today+1month% AND UNIX_TIMESTAMP(STR_TO_DATE(CONCAT("%format_date_string|Y|now%", " ", DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), "%m %d")), "%Y %m %d")) > %str_to_time|yesterday% ) OR (UNIX_TIMESTAMP(STR_TO_DATE(CONCAT("%format_date_string|Y|first day of next year%", " ", DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), "%m %d")), "%Y %m %d")) < %str_to_time|today+1month% AND UNIX_TIMESTAMP(STR_TO_DATE(CONCAT("%format_date_string|Y|first day of next year%", " ", DATE_FORMAT(DATE_ADD('1950-01-01 00:00:00', INTERVAL usermeta.meta_value SECOND), "%m %d")), "%Y %m %d")) > %str_to_time|yesterday% ) ) -- 按目标日期与今天的间隔天数升序排列,最近的员工排在最前面 ORDER BY DATEDIFF(target_date, CURDATE()) ASC;
关键修改说明
- 新增
target_date字段:自动判断取今年的生日/入职纪念日(如果还未过期),若已过期则取下一年的日期,确保计算的是距离当前最近的目标日期。 - 修正排序逻辑:用
DATEDIFF(target_date, CURDATE())计算目标日期与今天的天数差,按升序排列后,距离当前时间越近的员工会排在结果最前面。
你之前尝试的排序代码问题
- 混用了不同SQL方言的函数:原SQL使用MySQL语法,你写的
GETDATE()是SQL Server的函数,两者不兼容。 - 字段选择逻辑错误:
'fodselsdag' OR 'jubilaeum'这种写法无法正确指定字段,需要结合meta_key区分不同日期类型处理。 - 未考虑跨年场景:比如当前是12月时,明年1月的生日/纪念日没有被正确计算。
内容的提问来源于stack exchange,提问作者Marc Kroon
相关产品推荐
相关产品推荐

