MySQL如何正确查询含小数的最大值?book_progressive字段查询异常
解决MySQL中字符串类型字段取MAX值错误的问题
这个问题我之前也碰到过,本质是字符串类型的排序逻辑和数值类型不一样导致的!
为什么会返回99.01?
你的book_progressive字段应该是CHAR或者VARCHAR类型的字符串,MySQL在对字符串执行MAX()函数时,是按照**字典序(ASCII码顺序)**来比较的。字典序里,字符'9'的ASCII码比'1'大,所以"99.01"会被认为比"144.01"更大,这就出现了不符合预期的结果。
几种可行的解决方案
方案1:临时转换类型查询(不用改表结构)
如果不想动表结构,直接在查询时把字符串转成数值类型再计算最大值就行:
- 直接转成小数类型:
SELECT MAX(CAST(book_progressive AS DECIMAL(10,2))) FROM books_title;
或者用CONVERT函数:
SELECT MAX(CONVERT(book_progressive, DOUBLE)) FROM books_title;
- 精准提取整数部分(因为你的后缀都是.01):
如果确定所有值的格式都是X.01,可以提取小数点前的数字转成整数,这样结果更精准:
SELECT MAX(CAST(SUBSTRING_INDEX(book_progressive, '.', 1) AS UNSIGNED)) AS max_progressive FROM books_title;
得到的结果是144,需要原格式的话自己拼接.01就行。
方案2:修改字段类型(长期最优解)
如果这个字段本来就是用来表示序列数值的,最好直接把字段改成数值类型,一劳永逸:
- 先备份数据(重要!避免操作失误丢数据)
- 修改字段类型:
- 保留小数格式的话,改成
DECIMAL:
ALTER TABLE books_title MODIFY COLUMN book_progressive DECIMAL(10,2);- 因为后缀固定是
.01,也可以改成整数类型,只存前面的数字:
之后要输出原格式的话,用ALTER TABLE books_title MODIFY COLUMN book_progressive INT UNSIGNED;CONCAT拼接:
改完类型后,再用SELECT CONCAT(book_progressive, '.01') FROM books_title;MAX(book_progressive)就能得到正确的144.01(或者144)了。 - 保留小数格式的话,改成
方案3:保留字符串类型但统一格式
如果必须保留字符串类型,那可以把所有值补零到相同长度,让字典序和数值序一致。比如把"1.01"改成"001.01","99.01"改成"099.01":
- 先更新现有数据:
UPDATE books_title SET book_progressive = CONCAT(LPAD(SUBSTRING_INDEX(book_progressive, '.', 1), 3, '0'), '.01');
这里假设最大的数字是3位(144),所以用LPAD补到3位。之后新增数据的时候也要按照这个格式插入,这样MAX()就能返回正确的"144.01"了。
内容的提问来源于stack exchange,提问作者Frankie
相关产品推荐
相关产品推荐

