2011-10-24 11 views
5

Tengo una tabla que almacena las versiones tan bajoNúmero de versión de clasificación en SQL Server

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 

Mi requisito es que necesito para ordenarlos de manera que la salida será

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 

Pero si do por una simple orden no funciona como se esperaba

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 

Ayuda necesaria

+1

Este es un caso especial del problema general "no almacenar valores delimitados en columnas" –

Respuesta

1

Implementación de Brain Solución

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 
5

Esto generalmente se llama ordenamiento natural y no hay una manera fácil de hacerlo en SQL Server. En general, los datos deben dividirse en campos o segmentos de longitud fija de un campo. Se puede ordenar en esos campos para el orden deseado.

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

no puedo ver la solución utilizando la clasificación estándar, etc, pero creo que necesita la UDF que se suma a los "0" símbolos antes de cada símbolo, como

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 

y luego ordenar por estos valores modificados

0

La consulta SELECT está ordenando alfabéticamente, en lugar de numéricamente. Sin un procedimiento almacenado para agregar ceros iniciales en los componentes separados del número de versión para hacerlos todos de la misma longitud, no se puede (AFAIK) hacer esto en SQL.

8

Si está utilizando SQL Server 2008 o posterior, puede aprovechar al tipo de datos hierarchyid:

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

Me acabo de dar cuenta: no es necesario reemplazar el '.' con'/' , 'ORDER BY CAST ('/' + VersionNumber + '/' como hierarchyID)' funciona igual de bien. –

1

Si usted está en SQL Server 2005 o posterior y el número de posibles campos en los números de versión se fija, puede probar con el siguiente enfoque:

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) 

Todos los campos de un número de versión se extraen una a una y se convierten en números enteros, que luego se utilizan para la clasificación. (Básicamente, @Brian 'idea de s, como resulta.)

0

comprobar estos le ayuda

Select * From fin @tblVersion cerca substituyen (VersionNumber,'. ',' ')

Cuestiones relacionadas