如何使用SQL Server查询对“版本号”列进行排序

时间:2010-08-13 07:44:58

标签: sql sql-server sorting sql-server-2000

我想知道我们中间的SQL天才是否可以帮助我。

我在表VersionNo中有一列Versions,其中包含“版本号”值,例如

VersionNo
---------
1.2.3.1
1.10.3.1
1.4.7.2

我希望对此进行排序,但不幸的是,当我执行标准order by时,它被视为一个字符串,因此订单出现为

VersionNo
---------
1.10.3.1
1.2.3.1
1.4.7.2

以下内容,这就是我所追求的:

VersionNo
---------
1.2.3.1
1.4.7.2
1.10.3.1

所以,我需要做的是按相反的顺序排序数字(例如在a.b.c.d中,我需要按d,c,b,a排序以获得正确的排序我们)。

但我仍然坚持如何以GENERIC方式实现这一目标。当然,我可以使用各种sql函数(例如leftrightsubstringlencharindex)拆分字符串,但我可以' t保证版本号总是有4个部分。我可能有这样的列表:

VersionNo
---------
1.2.3.1
1.3
1.4.7.2
1.7.1
1.10.3.1
1.16.8.0.1

可以吗,有没有人有任何建议?非常感谢您的帮助。

4 个答案:

答案 0 :(得分:19)

如果您使用的是SQL Server 2008

select VersionNo from Versions order by cast('/' + replace(VersionNo , '.', '/') + '/' as hierarchyid);

What is hierarchyid

编辑:

2000年,2005年,2008年的解决方案:Solutions to T-SQL Sorting Challenge here

The challenge

答案 1 :(得分:3)

依赖于MySQL的SQL引擎,就像这样:

SELECT versionNo FROM Versions
ORDER BY
SUBSTRING_INDEX(versionNo, '.', 1) + 0,
SUBSTRING_INDEX(SUBSTRING_INDEX(versionNo, '.', -3), '.', 1) + 0,
SUBSTRING_INDEX(SUBSTRING_INDEX(versionNo, '.', -2), '.', 1) + 0,
SUBSTRING_INDEX(versionNo, '.', -1) + 0;

对于MySQL版本3.23.15以上

SELECT versionNo FROM Versions ORDER BY INET_ATON(ip);

答案 2 :(得分:1)

另一种方法:

假设你只有a,b,c,d,你也可以将数据分开到列并按a,b,c,d(所有desc)进行排序并得到前1行

如果你需要扩展到大于d来说e,f,g ......只需改变1,2,3,4到1,2,3,4,5,6,7等等查询

查询: see demo

create table t (versionnumber varchar(255))
insert into t values
('1.0.0.505')
,('1.0.0.506')
,('1.0.0.507')
,('1.0.0.508')
,('1.0.0.509')
,('1.0.1.2')


; with cte as 
(
    select 
    column1=row_number() over (order by (select NULL)) ,
    column2=versionnumber
    from t
    )

select top 1
    CONCAT([1],'.',[2],'.',[3],'.',[4])
from 
(
    select 
        t.column1,
        split_values=SUBSTRING( t.column2, t1.N, ISNULL(NULLIF(CHARINDEX('.',t.column2,t1.N),0)-t1.N,8000)),
        r= row_number() over( partition by column1 order by t1.N) 
    from cte t 
        join
        (
            select 
                t.column2,
                1 as N 
            from cte t  
                UNION ALL
            select 
                t.column2,
                t1.N + 1 as N
            from cte t 
                join
                (
                 select 
                    top 8000
                        row_number() over(order by (select NULL)) as N 
                 from 
                    sys.objects s1 
                        cross join 
                   sys.objects s2 
                ) t1 
            on SUBSTRING(t.column2,t1.N,1) = '.'
         ) t1
          on t1.column2=t.column2
)a
pivot
( 
    max(split_values) for r in ([1],[2],[3],[4])
   )p
  order by [1] desc,[2] desc,[3] desc,[4] desc

答案 3 :(得分:0)

如果可以,请更改架构,以使版本有4列而不是1列。然后排序很容易。