【问题标题】:Mysql order by with decimal and characterMysql order by 带小数和字符
【发布时间】:2022-01-28 06:12:29
【问题描述】:

我有一个包含以下行的表格。

id clause_no
1 5.8
2 5.9
3 5.1.1
4 5.10.2
5 5.1
6 5.10.2
7 5.4.3.2
8 5.40.3.2
9 5.6.3.2
10 5.40.3.3
11 K.8
12 L.26
13 K.3.2
14 Annex F

我想以以下格式显示它:

id clause_no
5 5.1
3 5.1.1
7 5.4.3.2
9 5.6.3.2
1 5.8
2 5.9
4 5.10.2
6 5.10.2
8 5.40.3.2
10 5.40.3.3
14 Annex F
13 K.3.2
11 K.8
12 L.26

我尝试了 order by,但它没有按预期工作。 PFB db-fiddle 链接:

db-fiddle

【问题讨论】:

  • subj 中提到的“浮点数”在哪里? PS。你的 MySQL 版本真的是 5.7.x 吗?
  • 我们可以假设clause_no 嵌套了多少层吗?
  • @TimBiegeleisen 最多 6 个点
  • @Akina 在我的本地,它显示 10.4.21-MariaDB。在直播中,是 5.7.23-23。
  • 适用于本地版本的简单解决方案无法实时运行。

标签: mysql


【解决方案1】:

好吧,我认为您必须拆分 clause_no 列,该列必须是字符串列(不是浮点数...)。需要确保它们按数字排序,因此 '10' > '5'..

ORDER BY CAST(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',1) AS UNSIGNED), 
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',2),'.',-1) AS UNSIGNED), 
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',3),'.',-1) AS UNSIGNED),
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',4),'.',-1) AS UNSIGNED),
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',5),'.',-1) AS UNSIGNED),
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(clause_no,'.0'),'.',6),'.',-1) AS UNSIGNED)

【讨论】:

  • 真的只需要附加一个“.0” 没有像'1.1.0' 这样的值并不能保证这样的值不能存在于真实数据中。但是如果表结构包含相应的约束,那么你是对的。
  • 因此,1.11.1.0 将按照相同的顺序随机排序。您可以将 LENGTH(clause_no) 作为最后一个排序列
  • 但在末尾添加更多“.0”并不能解决任何问题。
  • 感谢您的回答。还有一种可能,我忘记添加数据了。更新了数据库小提琴。在clause_no中也会有几个字符(例如:K.8),这些字符需要在所有数字排序后显示在最后。 ——
【解决方案2】:

您可以“规范化”您的 clause_no 值。适用于你的解决方案live,是5.7.23-23.版本。

SELECT id, clause_no
FROM test
JOIN (SELECT 1 num UNION SELECT 2 UNION SELECT 3
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) numbers 
    ON LENGTH(clause_no) - LENGTH(REPLACE(clause_no, '.', '')) >= num - 1
GROUP BY id, clause_no
ORDER BY GROUP_CONCAT(LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(clause_no, '.', num), '.', -1), 8, 0) ORDER BY num SEPARATOR '');

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=d4ce86391c7bc8a630b79fd4673abdf9

查询假设:

  1. 最大。 clause_no 中的组数为 6。可根据子查询展开增加。
  2. 组件的值包含不超过 8 位。可根据 LPAD 参数进行调整。

还有一种可能,我忘记添加数据了。更新了小提琴。少数字符也将在那里(例如:K.8),这些字符需要在所有数字排序后显示在最后。 – 你好

SELECT id, clause_no
FROM test
JOIN (SELECT 1 num UNION SELECT 2 UNION SELECT 3
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6) numbers 
    ON LENGTH(clause_no) - LENGTH(REPLACE(clause_no, '.', '')) >= num - 1
GROUP BY id, clause_no
ORDER BY GROUP_CONCAT(CASE WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(clause_no, '.', num), '.', -1) REGEXP '[^0-9]'
                           THEN RPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(clause_no, '.', num), '.', -1), 8, 0) 
                           ELSE LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(clause_no, '.', num), '.', -1), 8, 0) 
                           END ORDER BY num SEPARATOR '');

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=270e63d7823ed6076b033061e7da33ba

【讨论】:

  • 感谢您的回答。还有一种可能,我忘记添加数据了。更新了小提琴。少数字符也将在那里(例如:K.8),这些字符需要在所有数字排序后显示在最后。
  • @Hello 更新了小提琴。您必须更新问题本身!并更新小提琴的链接。 也会出现一些字符(例如:K.8) 1K.8? 2K3.8?
  • 不,它会以字符开头。我已经更新了问题,感谢您指出。
  • 在第二个小提琴链接中,数字排序受到影响,5.10.2在5.4.3.2之前显示
  • @Hello 正则表达式不正确...已修复。
【解决方案3】:

你可以试试:

SELECT * FROM clause_no ORDER BY INET_ATON(SUBSTRING_INDEX(CONCAT(clause_no,'.0.0.0'),'.',4))

但它最多只能使用 3 个小数点。这是因为这不是 INET_ATON 函数的预期用途,但它很适合这里。

【讨论】:

  • 好主意,除了他有 6 个字段或者可能 7 个字段
  • 是的,谢谢,更新了提到这一点的答案。
  • @ShivamAgrawal 感谢您的回答。还有一种可能,我忘记添加数据了。更新了数据库小提琴。在clause_no中也会有几个字符(例如:K.8),这些字符需要在所有数字排序后显示在最后。
猜你喜欢
  • 2023-03-17
  • 2022-01-07
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-02-22
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多