【问题标题】:Ordering issue concerning numbers and letters in MYSQL SELECT statementMYSQL SELECT 语句中有关数字和字母的排序问题
【发布时间】:2014-02-20 10:01:27
【问题描述】:

我有一个包含数字和字母的列“标签”的表格,例如:

1
2
3
4a
4b
10
11
12
20
Z1

当我运行以下查询时,我没有得到想要的顺序:

SELECT * FROM `items` ORDER BY `tag` ASC;

这将输出为 (1, 11, 12, 2, 20, 4a, 4b, P1)

然后我通过在查询中使用“+ 0”或“* 1”找到了一个不错的解决方法:

SELECT * FROM `items` ORDER BY `tag` + 0 ASC;

这将输出为 (Z1, 1, 2, 3, 4b, 4a, 10, 11, 12, 20),只是稍微好一点

有没有办法对这些值进行排序,使它们显示为:

(1, 2, 3, 4a, 4b, 10, 11, 12, 20, Z1)

我想避免添加订单列,因为我有 30,000 件商品,而标签只是较大类别的子集。

【问题讨论】:

  • SQLFiddle 似乎已关闭,因此无法转换我的 sql-server 解决方案...我认为您需要排序:字符串左侧的字母(不存在时为“0”),数字(从左或右),从右开始的字母(“0”表示不存在)。但我认为您可能需要重新考虑这是否是一个很好的排序依据。
  • 谢谢大家,我已经尝试了所有能找到的方法,但都没有好的结果。我只是要添加一个订单列并花几天时间手动对数据进行排序(到某个时间点)。

标签: php mysql select


【解决方案1】:

试试这个:

SELECT * FROM `items` ORDER BY  CAST(`tag` as UNSIGNED) ASC;

编辑:

SELECT * FROM items
ORDER BY (tag REGEXP '[0-9]^'),
         CASE WHEN tag REGEXP '^[0-9]' THEN tag*1 ELSE tag END;

【讨论】:

  • 嗨,这个输出(Z1、1、2、3、4a、4b 等)
【解决方案2】:

更新:这似乎是very non-trivial 在 MySQL 中实现的。即使您确实实施了它,我想它也会非常缓慢。如果您必须按此标签排序,我建议将其分成几列并将标签列作为这些列的计算连接


您的标签采用以下格式:可选字母集、整数、另一个可选字母集。要正确排序这些,您将提取标签的每个部分,以便您可以将字母作为字符串进行比较,将数字作为整数进行比较。

SQLFiddle 已关闭,因此以下是该问题的 SQLServer 解决方案,它可能会帮助您(或其他可以提供帮助的人)可视化如何在 MySQL 中执行此操作,尽管查询会非常不同。在下面的atag

SELECT a
   ,CASE WHEN a LIKE '[^0-9]%' 
         THEN LEFT(a, ISNULL(NULLIF(PATINDEX('%[^0-9][0-9]%', a ),0),LEN(a)))
         ELSE '' 
    END AS StartLetter   
   ,CAST(SUBSTRING(a 
                   ,PATINDEX('%[0-9]%', a )
                   ,(LEN(a)+2-PATINDEX('%[0-9]%', REVERSE(a)))-PATINDEX('%[0-9]%', a))
         AS INT) AS Number
   ,SUBSTRING(a
             ,LEN(a)+2-PATINDEX('%[0-9]%', REVERSE(a) )
             ,LEN(a)-1) AS EndLetter
FROM @t
ORDER BY STartLetter, Number, EndLetter

这会产生以下结果(对于您的数据 + 一些额外的测试数据):

+-----+-------------+--------+-----------+
|  a  | StartLetter | Number | EndLetter |
+-----+-------------+--------+-----------+
| 1   |             |      1 |           |
| 2   |             |      2 |           |
| 3   |             |      3 |           |
| 4ab |             |      4 | ab        |
| 4b  |             |      4 | b         |
| 10  |             |     10 |           |
| 11  |             |     11 |           |
| 12  |             |     12 |           |
| 20  |             |     20 |           |
| B1  | B           |      1 |           |
| B22 | B           |     22 |           |
| BA2 | BA          |      2 |           |
| Z1  | Z           |      1 |           |
| Z2b | Z           |      2 | b         |
| Z3  | Z           |      3 |           |
+-----+-------------+--------+-----------+

不过,鉴于仅对数据进行排序是多么复杂,我认为您首先需要重新考虑按列排序的决定。

【讨论】:

    【解决方案3】:

    您似乎想分隔以数字开头和以字母开头的字符串。 如果是这样,那么试试这个:

    SELECT tag, tag*1,(tag REGEXP '^[0-9]') FROM items
    ORDER BY (tag REGEXP '^[0-9]') DESC,
             tag*1,tag
    

    SQLFiddle demo

    【讨论】:

    • 嗨,这个输出(Z1、1、10、11、12、2、20等)
    • @user1024370 我已经更改了查询。立即尝试
    • 这很聪明,适用于测试数据。但是,如果您希望 Z1、Z2 和 Z10 也自然排序,它将失败。
    猜你喜欢
    • 2011-07-13
    • 2012-05-11
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2013-10-05
    • 2022-06-13
    • 1970-01-01
    相关资源
    最近更新 更多