¿Cómo comparar cadenas SQL que contienen numbers de versión como .NET System.Version class?

Posible duplicado:
¿Cómo comparar versiones de software usando SQL Server?

Soy completamente nuevo en sql, pero hoy encontré un error en una consulta SQL aquí en el trabajo que es muy importante. Entonces podría usar algo de ayuda:

Dada una cadena sql que representa una versión del producto

'15 .0.0.0 '

¿Existe una forma infalible de orderar o comparar esa cadena de caracteres similar a cómo .NET class System.Version compara instancias?

Entonces, dado tal constructo hipotético, o function o lo que sea, esperaría que '15 .5.568 'sería mayor que '15 .0.0.0'.

Gracias

Suponiendo SQL Server, y un número máximo conocido de partes, aquí hay una function definida por el usuario que hace lo mismo que parsename , pero funciona en cualquier cantidad de partes:

 Create Function dbo.VersionNthPart(@version as nvarchar(max), @part as int) returns int as Begin Declare @ret as int = null, @start as int = 1, @end as int = 0, @partsFound as int = 0 if @version is not null Begin Set @ret = 0 while @partsFound < @part Begin Set @end = charindex('.', @version, @start) If @end = 0 Set @partsFound = @part -- bail early else Begin Set @partsFound = @partsFound + 1 If @partsFound = @part Set @ret = Convert(int, substring(@version, @start, @end - @start)) Else Set @start = @end + 1 End End End return @ret End 

Ejemplo de uso:

 With tmp As ( Select '1.0.0.5' As Version Union All Select '1.5.0.06' Union All Select '1.0.0.06' Union All Select '2.0.0.0' Union All Select '2.0.1.1' Union All Select '15.5.568' Union All Select '15.0.0.0' Union All Select '15.15.1323.22' Union All Select '15.15.622.55' ) Select * From tmp Order By dbo.VersionNthPart(Version, 1), dbo.VersionNthPart(Version, 2), dbo.VersionNthPart(Version, 3), dbo.VersionNthPart(Version, 4) 

http://sqlfiddle.com/#!3/e942b/3

Simplemente agregando lo que sugirió @Gordon, aquí hay un ejemplo con ParseName

 ; WITH tmp AS ( SELECT '1.0.0.5' AS Version UNION ALL SELECT '1.5.0.06' UNION ALL SELECT '1.0.0.06' UNION ALL SELECT '2.0.0.0' UNION ALL SELECT '2.0.1.1' UNION ALL SELECT '15.15.1323.22' UNION ALL SELECT '15.15.622.55' ) SELECT * FROM ( SELECT CAST(PARSENAME(Version, 4) AS INT) AS col1 , CAST(PARSENAME(Version, 3) AS INT) AS col2 , CAST(PARSENAME(Version, 2) AS INT) AS col3 , CAST(PARSENAME(Version, 1) AS INT) AS col4 FROM tmp ) t0 ORDER BY col1, col2, col3, col4 

Si no tiene más de tres decimales, puede usar parsename. A continuación, rectifica los dos numbers de versión para los valores que tienen 4 caracteres, por lo que una comparación de cadenas debe escribirse. Tu ejemplo sería "0015.0000.0000.0000.0000".

 select (case when (right('0000'+coalesce(parsename(v1, 4), '', 4)) + right('0000'+coalesce(parsename(v1, 3), '', 4)) + right('0000'+coalesce(parsename(v1, 2), '', 4)) + right('0000'+coalesce(parsename(v1, 1), '', 4)) ) < (right('0000'+coalesce(parsename(v2, 4), '', 4)) + right('0000'+coalesce(parsename(v2, 3), '', 4)) + right('0000'+coalesce(parsename(v2, 2), '', 4)) + right('0000'+coalesce(parsename(v2, 1), '', 4)) ) then -1 when v1 = v2 then 0 else 1 end) as Comparison 

Tenga en count que parsename () solo funciona en hasta cuatro partes en el nombre.

Si solo desea orderar, entonces lo siguiente funcionará:

 order by (right('0000'+coalesce(parsename(v1, 4), '', 4)) + right('0000'+coalesce(parsename(v1, 3), '', 4)) + right('0000'+coalesce(parsename(v1, 2), '', 4)) + right('0000'+coalesce(parsename(v1, 1), '', 4)) )