2

我有一个如下所示的数据集:

+--------+
| Square |
+--------+
| A1     |
| A10    |
| A2     |
| A3     |
| A4     |
| A5     |
| A6     |
| A7     |
| A8     |
| A9     |
| B1     |
| B10    |
| B2     |
| B3     |
| B4     |
| B5     |
| B6     |
| B7     |
| B8     |
| B9     |

...

| AA1    |
| AA10   |
| AA2    |
| AA3    |
| AA4    |
| AA5    |
| AA6    |
| AA7    |
| AA8    |
| AA9    |
+--------+

前缀从 A#-Z# 开始,然后是 AA#-ZZ# 并继续,最多有 2 个字母(即它永远不会超过 ZZ)。数字后缀可以是任意长度(即A1、A10、A100、A1000等)。

我怎样才能对这些进行排序并使结果集如下所示:

+--------+
| Square |
+--------+
| A1     |
| A2     |
| A3     |
| A4     |
| A5     |
| A6     |
| A7     |
| A8     |
| A9     |
| A10    |
| B1     |
| B2     |
| B3     |
| B4     |
| B5     |
| B6     |
| B7     |
| B8     |
| B9     |
| B10    |

...

| AA1    |
| AA2    |
| AA3    |
| AA4    |
| AA5    |
| AA6    |
| AA7    |
| AA8    |
| AA9    |
| AA10   |
+--------+
4

5 回答 5

7

您需要重组您的表,否则您可能会遇到这样的低效查询,

SELECT  Square
FROM    Table1
ORDER   BY         
        CASE WHEN Square REGEXP '^[A-Z]{2}'
            THEN 1 
            ELSE 0
        END ASC,
        CASE WHEN Square REGEXP '^[A-Z]{2}'
            THEN LEFT(Square, 2)
            ELSE LEFT(Square, 1)
        END ASC,
        CASE WHEN Square REGEXP '^[A-Z]{2}'
            THEN CAST(RIGHT(Square, LENGTH(Square) - 2) AS SIGNED)
            ELSE CAST(RIGHT(Square, LENGTH(Square) - 1) AS SIGNED)
        END ASC

或者通过使用IF

SELECT  Square
FROM    Table1
ORDER   BY Square REGEXP '^[A-Z]{2}' ASC,
           IF(Square REGEXP '^[A-Z]{2}', LEFT(Square, 2), LEFT(Square, 1)),
           CAST(IF(Square REGEXP '^[A-Z]{2}', RIGHT(Square, LENGTH(Square) - 2), RIGHT(Square, LENGTH(Square) - 1)) AS SIGNED)
于 2013-04-01T12:33:00.657 回答
1

这里有更好的方式来构建你的表格

 letter  number  
   A      1
   A      2
   A      3
  .....so on

那么您的查询将像那样简单

  select concat(letter,number) as Square from your_table
  order by letter , number

在这里演示

于 2013-04-01T12:58:53.197 回答
0

如果我没记错的话,也许这会起作用:

SELECT Square
FROM table
ORDER BY CASE WHEN
     SUBSTR(Square, 2, 1) BETWEEN 'A' AND 'Z' 
     THEN CONCAT(LEFT(Square, 2),
         LPAD(RIGHT(Square, LENGTH(Square) - 2), 6, '000000'))
     ELSE CONCAT(LEFT(Square, 1),
         LPAD(RIGHT(Square(LENGTH(Square) - 1), 6, '000000'))
    END
于 2013-04-01T12:12:59.807 回答
0

如果可以的话,我强烈建议您更改数据库结构。这些应存储在 2 个单独的字段中。这是一种您可以执行排序的方法,但也可以让您朝着正确的方向重组表格:

select square, left(square,2) prefix, mid(square,3) suffix
from yourtable
where left(square,2) not regexp '[0-9]'
union
select square, left(square,1) prefix, mid(square,2) suffix
from yourtable
where left(square,2) regexp '[0-9]'
order by prefix, cast(sufix as signed)

SQL 小提琴演示

这样,您可以看到分解的前缀和后缀。这也可以通过没有联合的 case/if 语句来完成。

于 2013-04-01T12:40:53.333 回答
-1

我现在无法完全测试它,但它对我有用,而且它是与前一个完全不同的解决方案,我很想看看它是否适用于你的问题。我的非常相似,并且更改数据库结构不是一个选项,因为我正在排序的是用户输入......但我的解决方案适用于任何大小,并且比建议的要简单得多:

SELECT  Square
FROM    Table1
ORDER BY LENGTH(Square), Square
于 2016-09-14T21:07:19.053 回答