Sql Server中的版本号排序

Sql Server中的版本号排序,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个存储版本的表,如下所示 Declare @tblVersion table(VersionNumber varchar(100)) Insert into @tblVersion Values('1.3.1') Insert into @tblVersion Values('1.3.2.5') Insert into @tblVersion Values('1.4.1.7.12') Insert into @tblVersion Values('1.4.11.14.7') In

我有一个存储版本的表,如下所示

Declare @tblVersion table(VersionNumber varchar(100))
 Insert into @tblVersion Values('1.3.1')
 Insert into @tblVersion Values('1.3.2.5')
 Insert into @tblVersion Values('1.4.1.7.12')
 Insert into @tblVersion Values('1.4.11.14.7')
 Insert into @tblVersion Values('1.4.3.109.1')
 Insert into @tblVersion Values('1.4.8.66')

 Select * From @tblVersion

VersionNumber
1.3.1
1.3.2.5
1.4.1.7.12
1.4.11.14.7
1.4.3.109.1
1.4.8.66
我的要求是,我需要对它们进行排序,这样输出将是

VersionNumber
1.3.1
1.3.2.5
1.4.1.7.12
1.4.3.109.1
1.4.8.66
1.4.11.14.7
但是,如果按简单的顺序执行,它将无法按预期工作

Select VersionNumber
 From @tblVersion
 Order By VersionNumber

VersionNumber
1.3.1
1.3.2.5
1.4.1.7.12
1.4.11.14.7
1.4.3.109.1
1.4.8.66

需要帮助

这通常被称为自然排序,在SQL Server中没有简单的方法可以做到这一点。通常,需要将数据分解为字段或字段的固定长度段。它可以按照所需的顺序在这些字段上排序

VersionNumber VersionSort
1.3.1         0001.0003.0001
1.3.2.5       0001.0003.0002.0005
1.4.1.7.12    0001.0004.0001.0007.0012
1.4.11.14.7   0001.0004.0011.0014.0007
1.4.3.109.1   0001.0004.0003.0109.0001
1.4.8.66      0001.0004.0008.0066

我看不到使用标准排序等的解决方案,但我认为您需要在每个符号之前添加0符号的UDF,如

001.003.001
001.003.002.005
001.004.001.007.012
001.004.011.014.007
001.004.003.109.001
001.004.008.066

然后按这些更改的值排序

选择查询按字母顺序排序,而不是按数字排序。如果没有存储过程将前导零添加到版本号的各个组件中以使其长度相同,则无法在SQL中执行此操作。

如果您使用的是SQL Server 2008或更高版本,则可以利用hierarchyID数据类型:

select * from @tblVersion
order by CAST('/'+REPLACE(VersionNumber,'.','/')+'/' as hierarchyID)

如果您使用的是SQL Server 2005或更高版本,并且版本号中可能的字段数是固定的,则可以尝试以下方法:

SELECT t.*
FROM @tblVersion t
  CROSS APPLY (SELECT v = NULLIF(CHARINDEX('.', '.' + t.VersionNumber,        1), 0)) v1
  CROSS APPLY (SELECT v = NULLIF(CHARINDEX('.', '.' + t.VersionNumber, v1.v + 1), 0)) v2
  CROSS APPLY (SELECT v = NULLIF(CHARINDEX('.', '.' + t.VersionNumber, v2.v + 1), 0)) v3
  CROSS APPLY (SELECT v = NULLIF(CHARINDEX('.', '.' + t.VersionNumber, v3.v + 1), 0)) v4
  CROSS APPLY (SELECT v = NULLIF(CHARINDEX('.', '.' + t.VersionNumber, v4.v + 1), 0)) v5
ORDER BY
  CAST(SUBSTRING(t.VersionNumber, v1.v, v2.v - v1.v - 1) AS int),
  CAST(SUBSTRING(t.VersionNumber, v2.v, v3.v - v2.v - 1) AS int),
  CAST(SUBSTRING(t.VersionNumber, v3.v, v4.v - v3.v - 1) AS int),
  CAST(SUBSTRING(t.VersionNumber, v4.v, v5.v - v4.v - 1) AS int),
  CAST(SUBSTRING(t.VersionNumber, v5.v, 999) AS int)

版本号的所有字段都将逐个提取并转换为整数,然后用于排序。事实证明,基本上是“大脑”的想法。

大脑解决方案的实施

Declare @tblVersion table(VersionNumber varchar(100)) 
 Insert into @tblVersion Values('1.3.1') 
 Insert into @tblVersion Values('1.3.2.5') 
 Insert into @tblVersion Values('1.4.1.7.12') 
 Insert into @tblVersion Values('1.4.11.14.7') 
 Insert into @tblVersion Values('1.4.3.109.1') 
 Insert into @tblVersion Values('1.4.8.66') 

 --Select * From @tblVersion 

 ;With CTE AS
 (
    Select 
        Rn = Row_Number() Over(Order By (Select 1))
        ,VersionNumber
    From @tblVersion
)
,CTESplit AS
(
    SELECT 
            F1.Rn,
            F1.VersionNumber,
            VersionSort = 
                            Case 
                                    When Len(O.VersionSort) = 1 Then '000' + O.VersionSort
                                    When Len(O.VersionSort) = 2 Then '00' + O.VersionSort
                                    When Len(O.VersionSort) = 3 Then '0' + O.VersionSort
                                    When Len(O.VersionSort) = 4 Then O.VersionSort
                            End

    FROM
    (
        SELECT *,
        cast('<X>'+replace(F.VersionNumber,'.','</X><X>')+'</X>' as XML) as xmlfilter from CTE F
    )F1
 CROSS APPLY
 ( 
    SELECT fdata.D.value('.','varchar(50)') as VersionSort  
    FROM f1.xmlfilter.nodes('X') as fdata(D)) O
 )
 ,CTE3 As(
Select 
        --Rn 
        --,
        VersionNumber
        ,SortableVersion = 
                            Stuff(
                                    (Select '.' + Cast(VersionSort As Varchar(100))
                             From CTESplit c2
                             Where c2.Rn = c1.Rn
                             For Xml Path('')),1,1,'')
From CTESplit c1
Group By c1.Rn,c1.VersionNumber
)
Select VersionNumber
From CTE3
Order By SortableVersion
检查这些对你有帮助


从@tblVersion order by replaceVersionNumber,'.'中选择*这是一个特殊的通用情况,不在列中存储分隔值问题我刚刚意识到:不需要替换。使用/,按CAST“/”+VersionNumber+“/”排序,作为层次结构也同样有效。