Comment COMMANDER PAR des versions de version de logiciel typiques comme XYZ?

13

Étant donné un tableau "SoftwareReleases":

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

Comment puis-je produire cette sortie?

| 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
la source

Réponses:

22

Pour produire la sortie souhaitée, vous pouvez simplement:

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

On peut convertir un texttableau entier en un integertableau (pour trier 9avant 10).
On peut ORDER BYgrouper des types. C'est la même chose que la commande par chacun des éléments. Et les tableaux plus courts passent avant les tableaux plus longs avec une partie principale identique.

db <> violon ici
Old SQL Fiddle.

Erwin Brandstetter
la source
1
C'est bien. D'une certaine manière, cela trie correctement les valeurs manquantes, sans avoir à spécifier l'ordre des valeurs nulles: (1.6.9 -> 1.7 -> 1.7.1), plutôt que (1.6.9 -> 1.7.1 -> 1.7). Accepter celui-ci.
Chris Betti
2
Si vous avez affaire à des versions de Maven ou à des versions pouvant contenir des caractères non numériques, vous pouvez d'abord supprimer les caractères non numériques:string_to_array(regexp_replace(version, '[^0-9.]', '', 'g'), '.')::int[]
Samuel
Je l'utilise pour trouver la version maximale et cela fonctionne très 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 vous attendez plus d'éléments dans la chaîne de version, utilisez simplement plus d'index de tableau. Si l'index n'existe pas, le résultat sera nul (par exemple v[10]retournera null)

un cheval sans nom
la source
Avez-vous besoin de les convertir en nombres? Sinon, je m'attendrais 10à être entre 1et 2.
JNK
Ceci est confirmé par votre violon ...
JNK
Supprimer le mien en faveur de cela. string_to_array est beaucoup plus simple que regex.
Chris Betti
@JNK: c'est de cela qu'il v[1]::ints'agit. Il convertit la chaîne en un entier.
a_horse_with_no_name
La seule modification que j'apporterais à votre SQL est la commande par. Je suggère de supprimer desc et cela créera le jeu de résultats recherché par @Chris Betti.
Dim