¿Cómo ORDENAR POR versiones de lanzamiento de software típicas como XYZ?

13

Dada una tabla de "SoftwareReleases":

| id | version |
|  1 | 0.9     |
|  2 | 1.0     |
|  3 | 0.9.1   |
|  4 | 1.1     |
|  5 | 0.9.9   |
|  6 | 0.9.10  |

¿Cómo produzco esta salida?

| id | version |
|  1 | 0.9     |
|  3 | 0.9.1   |
|  5 | 0.9.9   |
|  6 | 0.9.10  |
|  2 | 1.0     |
|  4 | 1.1     |
Chris Betti
fuente

Respuestas:

22

Para producir el resultado deseado, puede simplemente:

SELECT id, version
FROM   versions
ORDER  BY string_to_array(version, '.')::int[];

Uno puede lanzar una textmatriz completa a una integermatriz (para ordenar 9antes 10).
Uno puede ORDER BYordenar tipos. Esto es lo mismo que ordenar por cada uno de los elementos. Y las matrices más cortas vienen antes que las más largas con una parte delantera idéntica.

db <> violín aquí
Old SQL Fiddle.

Erwin Brandstetter
fuente
1
Esto es genial. De alguna manera, esto ordena los valores faltantes correctamente, sin tener que especificar el orden de los valores nulos: (1.6.9 -> 1.7 -> 1.7.1), en lugar de (1.6.9 -> 1.7.1 -> 1.7). Aceptando este.
Chris Betti
2
Si está tratando con versiones de Maven o versiones que pueden contener caracteres no numéricos, primero puede eliminar los caracteres no numéricos:string_to_array(regexp_replace(version, '[^0-9.]', '', 'g'), '.')::int[]
Samuel
Lo uso para encontrar la versión máxima y funciona muy bienSELECT max(string_to_array(build_version, '.')::int[]
Joviano Dias
6
select id,
       name, 
       v[1] as major_version,
       v[2] as minor_version,
       v[3] as patch_level
from (
   select id, 
          name, 
          string_to_array(version, '.') as v
   from versions
) t
order by v[1]::int desc, v[2]::int desc, v[3]::int desc;

SQLFiddle: http://sqlfiddle.com/#!15/c9acb/1

Si espera más elementos en la cadena de versión, simplemente use más índices de matriz. Si el índice no existe, el resultado será nulo (por ejemplo v[10], volverá null)

un caballo sin nombre
fuente
¿Necesitas convertirlos a números? De lo contrario, esperaría 10estar entre 1y 2.
JNK
Esto lo confirma tu violín ...
JNK
Eliminando el mío a favor de esto. string_to_array es mucho más simple que regex.
Chris Betti
@JNK: de eso v[1]::intse trata. Lanza la cadena a un entero.
a_horse_with_no_name
El único cambio que haría en su SQL es el orden por. Sugiero eliminar desc y eso creará el conjunto de resultados que @Chris Betti está buscando.
Dom