问题描述
我们的系统某一处业务逻辑需要查询某个表里面一个字段的最大值。sql不难,就是一两个join。 一直运行没有问题。 但是某一天,突然发现这个地方有点问题,没有查询出来想要的结果。 导致用户无法选择想要的任务。
问题排查
找过来之后,第一直觉是他的操作有问题,但是仔细确认之后,发现用户的操作并没有问题。数据本身是有的,但是并没有被查询出来。 于是就找到这段SQL,拿出来,去数据库查询一下。发现确实没有得到正确的结果。那么很明显问题就是出在这段SQL上。 但是发现这部分逻辑在开发环境上无法复现,察觉到不简单。 于是将SQL分段进行排查,使用其中的第一段查询的时候发现问题了,这部分SQL的查询结果其实已经出问题了。所以后面总的结果有问题就说得通了。
问题复现
错误情况
这里将SQL与数据库结构简化一下:
select max(test2) as exec_id, test1 from test group by test1;
- 数据:
test1 : int test2: varchar 这段SQL的逻辑很简单,我们就是想要分组的情况下,找出每个test1的值对应的最大的test2的值
SQL执行结果: 很明显不正确。 这个时候大概知道了 可能是MAX这个函数引起的。 那么为什么会引起呢。 考虑到 test2字段的字段类型:varchar 。 大概猜到跟这个也有关系。
正常情况
将test2的字段类型改成int。这个时候再去执行SQL
SQL执行结果:
问题结论
那么就能看出来,是因为 MAX() 函数作用在varchar这种字符类型列上的时候,比较逻辑并不是按照int类型的比较逻辑。 从MySQL官方文档的解释来看: MAX() may take a string argument; in such cases, it returns the maximum string value 当MAX函数作用在一个字符类型上的时候,会返回最大的字符值。
那么怎么修复这个问题呢,改字段不太可取 动的地方比较多。 那么就用改SQL的方式来实现好了
select max(test2+0) as exec_id, test1 from test group by test1;
这样的SQL就能够做到将test2作为 int来进行比较。 能够得出正确的值。
Final
记录一下,下次不要再这样用MAX函数了
|