Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Version number sorting in Sql Server

I have a table that stores the versions as under

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

My requirement is that I need to sort them so that the output will be

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

But if do a simple order by it does not work as expected

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

Help needed

like image 873
priyanka.sarkar Avatar asked Oct 24 '11 03:10

priyanka.sarkar


3 Answers

If you are using SQL Server 2008 or later, you can leverage the hierarchyID data type:

select * from @tblVersion
order by CAST('/'+REPLACE(VersionNumber,'.','/')+'/' as hierarchyID)
like image 168
Steve Kass Avatar answered Sep 28 '22 16:09

Steve Kass


This is generally called natural sort and there is no easy way to do it in SQL Server. Generally the data needs to be broken into fields or to fixed length segments of a field. It can be sorted on those field(s) for the desired order.

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
like image 41
Brian Avatar answered Sep 28 '22 15:09

Brian


If you are on SQL Server 2005 or later and the number of possible fields in version numbers is fixed, you could try the following approach:

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)

All fields of a version number are extracted one by one and converted to integers, which are then used for sorting. (Basically, @Brian's idea, as it turns out.)

like image 29
Andriy M Avatar answered Sep 28 '22 14:09

Andriy M