关联表查询仅取首条变更记录时MIN函数返回MAX值异常排查
问题根因分析
你的子查询逻辑本身是符合取每个test_id首次变更时间的需求的,出现部分结果返回最大created_on的情况,基本是以下两类原因导致:
1. 同名字段覆盖问题(最常见)
你外层查询直接用了select *,如果tests表本身也存在名为created_on的字段,那么多表关联返回结果时,同名字段会被先出现的表的取值覆盖(不同数据库的处理规则略有差异,部分数据库会保留后出现的关联表的同名字段取值,还有部分数据库会直接给同名字段加后缀重命名,但如果没有显式指定别名,很容易出现取值混淆),你看到的所谓“最大created_on”本质上是tests表自身的created_on字段值,而不是子查询计算出来的首次变更时间。
2. 时间戳排序规则异常
你提到created_on是UNIXTIMESTAMP类型,但如果实际表结构中该字段的存储类型是字符串(CHAR/VARCHAR)而非数值型(INT/BIGINT),当存在不同长度的时间戳值时(比如9位的2001年前的时间戳和10位的2001年后的时间戳),字符串排序会按字典序计算MIN,而非按时间戳的数值大小计算,就会出现得到的MIN值实际对应更大时间的异常。
修复方案
显式指定查询字段,给计算出的首次变更时间加独立别名,同时强制转换字段类型规避排序异常即可:
select tests.*, tc.first_change_time from tests left join ( select MIN(CAST(created_on AS UNSIGNED)) as first_change_time, test_id from `test_changes` group by test_id ) as tc on tests.id = tc.test_id
未编辑过的测试记录对应的first_change_time会返回NULL,符合你的查询需求。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

