Mysql varchar类型中列的Order by

Mysql varchar类型中列的Order by,mysql,sql,sql-order-by,Mysql,Sql,Sql Order By,我有下面的列strand,它是按升序排列的,但它在3.1之后取3.10,而不是3.2 该列为varchar类型 Strand 3.1 3.1.1 3.1.1.1 3.1.1.2 3.1.2 3.1.2.1 3.10 # wrong 3.10.1 # wrong 3.10.1.1 # wrong 3.2 <- this should have been after 3.1.2.1 3.2.1 3.2.1.1 .. 3.9

我有下面的列strand,它是按升序排列的,但它在3.1之后取3.10,而不是3.2

该列为varchar类型

 Strand
 3.1
 3.1.1
 3.1.1.1
 3.1.1.2
 3.1.2
 3.1.2.1
 3.10       # wrong  
 3.10.1     # wrong
 3.10.1.1   # wrong
 3.2        <- this should have been after 3.1.2.1
 3.2.1
 3.2.1.1
 ..
 3.9
 3.9.1.1
         <- here is where 3.10 , 3.10.1 and 3.10.1.1 should reside

如何确保以正确的方式对其进行排序,以便最终获得3.10、3.10.1和3.10.1.1。您可以根据字段的整数值对结果进行排序。您的代码看起来像

select [myfield]from [mytable] order by 
convert(RPAD(replace([myfield],'.',''),4,0),UNSIGNED INTEGER);
在此代码中,替换功能将清除圆点(.)

希望有帮助

您必须规范化每组数字

SELECT * FROM [table1]
ORDER BY CONCAT(
    LPAD(SUBSTRING_INDEX(Strand,'.',1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(Strand,'.',2),'.',-1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(Strand,'.',3),'.',-1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX(Strand,'.',3),'.',-1),3,'0'));
样本

mysql> SELECT CONCAT(
    ->     LPAD(SUBSTRING_INDEX('3.10.1.1','.',1),3,'0'), '-',
    ->     LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX('3.10.1.1','.',2),'.',-1),3,'0'), '-',
    ->     LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX('3.10.1.1','.',3),'.',-1),3,'0'), '-',
    ->     LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX('3.10.1.1','.',3),'.',-1),3,'0'));
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| CONCAT(
    LPAD(SUBSTRING_INDEX('3.10.1.1','.',1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX('3.10.1.1','.',2),'.',-1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRING_INDEX('3.10.1.1','.',3),'.',-1),3,'0'), '-',
    LPAD(SUBSTRING_INDEX(SUBSTRI |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 003-010-001-001                                                                                                                                                                                                                                                  |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)
如果数据中的点(
)不超过3,可以尝试以下操作:

select *
from demo
order by replace(Strand, '.', '') * pow(10, (3 + length(replace(Strand, '.', '')) - length(Strand)))
如果点不确定,您可以在这里使用子查询来获取点的最大数量:

select demo.Strand
from demo
cross join (
    select max(length(Strand) - length(replace(Strand, '.', ''))) as num from demo
) t
order by replace(Strand, '.', '') * pow(10, (num + length(replace(Strand, '.', '')) - length(Strand)))
请参阅Rextester中的

如您所见,我在
orderby
子句中使用了函数

1)
replace(Strand,“,”)
会给我们一个整数,比如:
替换('3.10.1.1',','')
=>
31011

2)
(3+length(replace(Strand),“,”)-length(Strand))
将给出点的计数,该点的最大点数减去
Strand中点的计数,如:
3.1
=>2
3)
pow
将X的值提升为Y的幂

因此,样本数据的计算如下:

3100
3110
3111
3112
3120
3121
31000
31010
31011
3200
3210
3211
3900
3911
通过这些NUM,您将获得正确的排序。

因为“strand”列是文本数据,所以它将按字母顺序排列。要使其按您的要求排序,您应该在插入或更新数据之前格式化数据。假设每个级别的最大数字为3,则数据的格式应如下所示

 003.001
 003.001.001
 003.001.001.001
 003.002
 003.002.001
 003.002.001.001
 003.010
 010.001
替代方法是将“串”列拆分为多个列。每个列将存储每个级别的数据,例如

Level1 | Level2 | Level3 ... 
3      | 1      | 0
3      | 1      | 1
3      | 2      | 0
...
3      | 10     | 0
这些列的数据类型应该是number,然后您应该能够按这些列排序

试试这个:

DROP TABLE T1;
CREATE TABLE T1 (Strand VARCHAR(20));
INSERT INTO T1 VALUES ('3.1');
INSERT INTO T1 VALUES('3.1.1');
INSERT INTO T1 VALUES('3.1.1.1');
INSERT INTO T1 VALUES('3.1.1.2');
INSERT INTO T1 VALUES('3.2');
INSERT INTO T1 VALUES('3.2.1');
INSERT INTO T1 VALUES('3.10');
INSERT INTO T1 VALUES('3.10.1');

SELECT * FROM T1 
ORDER BY STRAND;


SELECT *
  FROM T1 
  ORDER BY 
    CAST(SUBSTRING_INDEX(CONCAT(Strand+'.0.0.0.0','.',1) AS UNSIGNED INTEGER) *1000 +
    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(Strand,'.0.0.0.0'),'.',2),'.',-1)  AS UNSIGNED INTEGER) *100 +
    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(Strand,'.0.0.0.0'),'.',3),'.',-1) AS UNSIGNED INTEGER) *10 +
    CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(Strand,'.0.0.0.0'),'.',4),'.',-1)  AS UNSIGNED INTEGER)
未指定的输出:

    Strand
1   3.1
2   3.1.1
3   3.1.1.1
4   3.1.1.2
5   3.10
6   3.10.1
7   3.2
8   3.2.1
输出顺序:

    Strand
1   3.1
2   3.1.1
3   3.1.1.1
4   3.1.1.2
5   3.2
6   3.2.1
7   3.10
8   3.10.1

从左到右的字符将按顺序排列。。。。。。。首先是“3”,然后是“.”,然后是“1或2”,然后是“0或”。什么是“错误”这里是您对字符串比较工作原理的理解……实际上您不能。如果你有3.1.1、3.1.100、3.2.1呢?对不起,我想我现在已经更正了(之前,我粘贴了一个以前的版本,每个字符串上都没有CONCAT)
    Strand
1   3.1
2   3.1.1
3   3.1.1.1
4   3.1.1.2
5   3.2
6   3.2.1
7   3.10
8   3.10.1