MySql varchar 排序

标签 mysql sorting varchar

我有另一个关于与其他人完全相同的问题的问题。我阅读了很多论坛和相关内容,但找不到答案。我正在使用 LPAD,因为我得到了最接近我需要的结果,但它仍然不是我想要的。

ORDER BY LPAD(`my_value`, '500', '0') ASC

记录现在看起来像这样:

Mova 16
Mova 110
Mova 125
Mova 140
Mova 180
Mova 160N

但我需要它们的顺序是:

Mova 16
Mova 110
Mova 125
Mova 140
Mova 160N
Mova 180

那么,我该如何实现呢?

我必须注意,这个表中还有其他记录,例如:

"GIACOMINI" R780 DN15 v/2 kampinis
"GIACOMINI" R780 DN20 v/3 kampinis
"GIACOMINI" R780 DN25 v/1 kampinis

还有更多......这些也应该适合这种情况。

最佳答案

我的想法是将您的列转换为固定长度的字符串,字母数字字符和数字按 block 对齐,例如

Input string                       | aligned string
---------------------------------------------------------------------------------------
Mova 16                            | MOVA......0000000016
Mova 110                           | MOVA......0000000110
Mova 180                           | MOVA......0000000180
Mova 160N                          | MOVA......0000000160N.........
"GIACOMINI" R780 DN15 v/2 kampinis | GIACOMINI.R.........0000000780DN........000..etc.
"GIACOMINI" R780 DN20 v/3 kampinis | GIACOMINI.R.........0000000780DN........000..etc.

然后我们可以使用对齐的字符串对行进行排序,但要获得结果我们需要创建一个自定义函数:

DROP FUNCTION IF EXISTS strformat;
SET GLOBAL  log_bin_trust_function_creators=TRUE; 
DELIMITER |
CREATE FUNCTION strformat(str VARCHAR(128))
RETURNS VARCHAR(128)
BEGIN
  DECLARE i INT;
  DECLARE last INT;
  DECLARE curr INT;
  DECLARE res VARCHAR(128);
  DECLARE block VARCHAR(10);

  SET res='';
  SET block='';
  SET i=1;

  IF LENGTH(str) = 0 THEN
    RETURN NULL;
  END IF;

  WHILE i <= LENGTH(str) DO
    SET curr=IF(MID(str, i, 1) RLIKE '[A-Z,a-z]', 1,
                  IF(MID(str, i, 1) RLIKE '[0-9]', 2, 0));

    IF (block='') OR (last=curr) THEN
      SET block = CONCAT(block,
                    IF((curr=1) OR (curr=2), MID(str, i, 1), ''));
    ELSE
      IF last=2 THEN
        SET res = CONCAT(res,
                    REPEAT('0', 10 - LENGTH(block)), block);
      ELSE
        SET res = CONCAT(res,
                    block, REPEAT(' ', 10 - LENGTH(block)));
      END IF;
      SET block = IF((curr=1) OR (curr=2), MID(str, i, 1), '');
    END IF;

    SET last=curr;
    SET i = i + 1;
  END WHILE;

  IF curr=1 THEN
    SET res = CONCAT(res, block, REPEAT(' ', 10 - LENGTH(block)));
  ELSEIF curr=2 THEN
    SET res = CONCAT(res, REPEAT('0', 10 - LENGTH(block)), block);
  END IF;

  RETURN UCASE(res);
END;
|
DELIMITER ;

(此处每个 block 必须限制为 10 个字符)。

然后您可以通过以下方式订购:

ORDER BY strformat(`my_value`)

关于MySql varchar 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14584364/

相关文章:

algorithm - 持续更新优先级队列的最佳算法/数据结构

c# - 对 DataTable 进行排序不起作用

mysql - SQL 查询找不到正确答案

MySQL查询仅选择日期组的最后一行

python - 索引超出范围 - Python 中的快速排序

sql-server - 当所需长度 <8000 时,TEXT 比 varchar 有什么优势?

sql - 将 GUID 转换为 varchar(32)

sql - SQL Server 中的 LIKE 运算符区分大小写吗?

php - 使用锁表时事务+回滚

mysql - 从 MySQL 数据库中删除选定的 tableView 行