简体   繁体   中英

MAX(Column name) doesn't return exact maximum value

I've a table test with columns id and code . It will look like this:

id     code

1      AF1
2      AF5
3      AF6
4      AF9
5      AF45

To get the maximum code value, I'm trying with an sql-instruction like:

SELECT MAX(code) from test

But, it doesn't return the desired result. It returns AF9 as the maximum value.

Now, my questions are :

  • Whether the prefix AF causing the problem?
  • How should I get the desired result?

AR9 is the maximum value. The comparisons are as strings.

If you want to compare part of the string as a number, then you need to convert them.

One method is using substring() and cast() :

order by substring(code, 1, 2),
         cast(substring(3, 10) as int)

Or, alternatively, there is a trick using the string length if you have no zero padded numbers:

order by length(code), code

Note: The functions for string length and substring operations vary depending on the database, so the exact functions might vary, depending on the system you are using.

There is no natural sorting order in MySQL. A couple of ways to go about this, outside crafty queries. (Crafty queries can become expensive when indexes won't be used for the sorting order.)

  • If all your prefixes are AF , you're better off removing the prefix and simply storing integers.
  • If you have other prefixes, have separate columns for storing the string and integer parts.
  • Left-pad the numeric part of your codes with zeros; ie. AF0045 and keep as strings. You wouldn't be able to use MAX() on a string, but you could always ORDER BY code DESC LIMIT 1 . This is obviously more performance-expensive, but still probably cheaper than using substrings etc.

If you want to just remove the AF prefix , you can do UPDATE test SET code = replace(code, 'AF', '') and then convert the column to integer. If you just convert the column to integer with your current code format, it'll be full of zero and your current data will be lost.

If a code were, say, 45AF , it'd become "45", but AF45 cast to integer returns 0 due to a leading non-numeric part. And if your MySQL were set to strict, you'd get an error about truncated data instead. So cleaning up before column conversion is a good practice.

If you have multiple prefixes you need to store separately, then use an UPDATE ... SELECT using the substring and cast method in Gordon's answer, like so (after creating the extra columns):

UPDATE test SET 
code_prefix = SUBSTRING(code, 1, 2), 
code_number = CAST(SUBSTRING(code, 3, 10) AS INT);

That'll normalize your structures on the basis of your source code format, storing parts of your original code in separate string and integer columns -- and you can use MAX(code_number) on the integers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM