mysql - 如何对没有特定格式的数字和字母的 varchar 进行排序?

标签 mysql sql sql-server sql-order-by

我有一个名为 MR 的列,它是一个 varchar。当我使用 ORDER BY 运行查询时,它的排序似乎不正确。

select MR, LName, FName 
from users
order by MR

结果:

MR        | LNAME | FNAME
----------+-------+-------
1234-234  | HEN   | LO
2343MA2   | SY    | JACK
MR20001   | LINA  | MARY
MR200011  | TEST  | CASE
MR20002   | KO    | MIKE

为什么 MR200011 显示在 MR20002 之前? 关于如何正确排序这个问题,大家有什么想法吗? MR的格式不固定。

最佳答案

您正在按字符串排序,而不是按数字值排序。位置 7 中的字符是要比较的差异:

MR200011 
MR20002 
      ^

因为“2”>“1”,这就是您最终得到的顺序。第 8 个字符永远不会被比较,因为基于字符的排序顺序不依赖于它。

要“修复”此问题,请创建一个存储函数,该函数接受 varchar 值,并返回一个新的“排序字符串”,该字符串将数字组件填充到固定长度。

例如

MR20002  -> MR0020002
MR200011 -> MR0200011

但更重要的是,如果您有两个数字 block ,它们不会被损坏:

A1234-234  -> A000000001234-000000000234
A1234-5123 -> A000000001234-000000005123

以下函数在 sql-server 上执行此转换 - 您必须为 mysql 调整此函数:

create function dbo.get_numeric_sort_key(@value varchar(100)) 
    returns varchar(200)
as
begin
   declare @pad_characters varchar(12)
   declare @numeric_block varchar(12)
   declare @output varchar(200)
   set @pad_characters = '000000000000'
   set @output = ''
   set @numeric_block = ''

   declare @idx int
   declare @len int
   declare @char char(1)
   set @idx = 1
   set @len = len(@value)
   while @idx <= @len
   begin
     set @char = SUBSTRING(@value, @idx, 1)
     if @char in ('0','1','2','3','4','5','6','7','8','9') 
     begin
        set @numeric_block = @numeric_block + @char
     end
     else
     begin
        if (@numeric_block <> '')
        begin
          set @output = @output + right(@pad_characters + @numeric_block, 12)
          set @numeric_block = ''
        end
        set @output = @output + @char
     end
     set @idx = @idx + 1
   end

   if (@numeric_block <> '')
     set @output = @output + right(@pad_characters + @numeric_block, 12)

   return @output
end

然后更改您的 order by 子句以使用新函数:

select MR, LName, FName 
from users 
order by dbo.get_numeric_sort_key(MR)

如果您有大量数据,则值得将计算字段添加到表定义的末尾(由此函数填充),这样您就不必在每次运行此查询时都进行扫描.

关于mysql - 如何对没有特定格式的数字和字母的 varchar 进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14497692/

相关文章:

php - 如何将 fetch(PDO::FETCH_ASSOC) 中的单个值或整个数组存储在变量中?

mysql - 缺少 NULL 答案的 SQL JOIN 问题和答案

sql - 为什么我用一个个人id加入多个表时得到0行?

php - Symfony Doctrine 迁移 $connection 没有权限

php - 有比 "LIKE"更好的 MySQL 字符串比较吗?

mysql - SQL : selecting rows based on a 2-column criteria

mysql - 如何从同一个表中的子查询更新列?

c# - 如何执行更新查询?

c# - EF6 从数据库返回错误数据

sql-server - SSIS 平面文件无法处理 NUL (\x00) 值?