[SQL]Tri naturel sous PostGre

Tri naturel sous PostGre [SQL] - SQL/NoSQL - Programmation

Marsh Posté le 20-07-2004 à 16:55:48    

Salut,
 
Je suis en train de bosser sur un projet d'intranet et lorsque je sors les libellé des articles pour les devis il me fait un tri non naturel (120 avant 20 par exemple).
 
Je sais que Natsort existe en php mais il ne permet que te traiter un tableau de strings alors que j'ai un tableau d'objets qui vient de ma base PostGre...
 
Avant de me lancer dans la mise en place d'une fonction pour retraiter tout cela j'aimerais savoir s'il n'y a pas de méthode de tri naturel directement sous PostGre... ?
 
Merci d'avance

Reply

Marsh Posté le 20-07-2004 à 16:55:48   

Reply

Marsh Posté le 20-07-2004 à 17:06:56    

Je n'en connait pas de tout fais sous Pg, mais tu peux toujours te définir ton propre opérateur de tri si tu trouve cela trop couteux de le faire ne php.

Reply

Marsh Posté le 20-07-2004 à 17:08:45    

cad ? developpes pliz

Reply

Marsh Posté le 20-07-2004 à 17:15:38    

ORDER BY accepte la clause USING dans laquelle tu peux demander d'utiliser un opérateur de tri que tu aurais toi-même implémanter. Par défaut, il ne connait que < et > mais tu peux te créer une autre classe d'opérateur qui réaliserait le tri naturel et appeler cet opérateur.

Reply

Marsh Posté le 20-07-2004 à 17:17:10    

Mais bon, dans ce cas, il est également préférable de se définir un type propre pour les colonnes afin de ne pas surchager un opérateur malencontreusement.

Reply

Marsh Posté le 20-07-2004 à 17:37:46    

ton 120 et ton 20, ce serait pas des chaines de caracteres par hasard ? :D
dans ce cas, 120 viens avant 20, c'est l'ordre naturel ;)

Reply

Marsh Posté le 20-07-2004 à 17:40:08    

ce n'est pas ce que l'on appelle le tri naturel.

Reply

Marsh Posté le 20-07-2004 à 17:40:34    

c pas l'ordre naturel 120 avant 20... C'est l'ordre naturel pour windaube oui surement pas pr moi :d
 
Avec php t'as Natsort qui te permet de traiter de l'alphanumérique en ordre naturel mais moi c'est un tableau d'objet que j'ai a traiter c pour ça que je cherches à le faire directement via la requete PgSQL

Reply

Marsh Posté le 20-07-2004 à 21:19:48    

C'est l'ordre naturel de n'importe quel système.
 
Si c'est un type alpha-numérique, c'est alors un tri alphabétique qui est le tri naturel, y'a pas à tortiller.
 
Ensuite, un simple ORDER BY CAST(monChamp as NUMBER) résoudra le problème. (syntaxe SQL Server)
 
Et si le champ contient à la fois des nombres et des mots, à ce moment un simple LPAD(monChamp, 10) permettra de faire l'équivament de "natsort". (syntaxe Oracle)
 
Les neurronnes ça se met en marche avant de se poser ce genre de questions... Franchement, pas savoir faire un tri alphabétique, c'est preuve d'une manque flagrant de réflexion.
 
Oui, je sais, je casse tout le monde ce soir, mais je suis de mauvais poil, depuis hier au taff ils ont coupé l'accès au forum et je peux plus décompresser la journée en regardant les problèmes des autres.

Reply

Marsh Posté le 20-07-2004 à 21:44:47    

euh... t'es au courrant que lpad ne fais absolument pas ce qui est demandé et que le cast non plus? :heink:

Reply

Marsh Posté le 20-07-2004 à 21:44:47   

Reply

Marsh Posté le 21-07-2004 à 20:32:30    

Pourquoi ? La question c'est pas d'avoir ça ?
 
977
12
578
5
 
Une fois trié :
 
5
12
578
977
 
 
Bah excuse-moi, mais un LPAD ou un CAST permettront RIGOUREUSEMENT d'obtenir ce tri.
 
Le LPAD permettant en sus de trier les données même si elles ne sont pas que numériques :
 
sdf
977
12
tr
5r78
5
 
Une fois trié :
 
5
12
tr
977
sdf
5r78


Message édité par Arjuna le 21-07-2004 à 20:33:00
Reply

Marsh Posté le 21-07-2004 à 21:48:17    

lpad, ca permet de rajouter des caractères devant, pour autant que le pad soit plus grand que la taille du champs, mais alors tu modifies le résultat retourné.
 
En outre, le résutlat que tu donnes dans ton exemple n'est pas le tri naturel "classique" dont je suppose que ze-angel désire. Le résultat attendu serait plutôt
5
12
977
5r78
sdf
 
Du moins si l'on s'en réfère à la définition du tri naturel ( http://www.naturalordersort.org/ )

Reply

Marsh Posté le 21-07-2004 à 22:00:17    

ORDER BY LPAD(tab) j'ai dit :o
 
PS: et pourquoi les chaînes de caractères seraient à la fin ? Surtout la 5r78, je ne vois pas ce qui peut expliquer ce tri... En tout cas je n'y voit rien de naturel.


Message édité par Arjuna le 21-07-2004 à 22:01:07
Reply

Marsh Posté le 21-07-2004 à 22:02:14    

parce que c'est comme ça comme fonctionne le tri naturel, que tu le trouves naturel ou pas [:spamafote]

Reply

Marsh Posté le 21-07-2004 à 22:03:24    

Sinon, c'est bien simple... (pseudo code, je ne connais pas la fonction oracle qui permet de détecter un nombre, et je ne pense pas que le DECODE existe sous MySQL, mais il doit bien y avoir un équivament pour ces deux fonctions)
 
ORDER BY isNumeric(tab), decode(isNumeric(tab), true, lpad(tab, 10), tab)
 
A ce moment, ca fera le tri que tu indiques, mais je trouve que c'est bien compliqué pour un résultat pas convainquant (à mon goût)


Message édité par Arjuna le 21-07-2004 à 22:04:16
Reply

Marsh Posté le 21-07-2004 à 22:08:52    

ca marchera toujours pas. Suppose 5rvst et 53gh, dans le tri naturel, cela donnerai l'ordre 5rvst puis 53gh. Avec ta méthode, on aura le résultat inverse parce que 53gh n'est pas numérique mais plus court que 5rvst.

Reply

Marsh Posté le 21-07-2004 à 22:21:47    

:heink: et pour quelle raison cet ordre (c'est foncièrement débile ce truc, je vois pas l'intérêt de trier suivant cet ordre, ça ne m'étonne pas qu'il n'existe pas dans les SGBD... Y'a qu'un langage de merde pour porposer un truc pareil !)


Message édité par Arjuna le 21-07-2004 à 22:22:08
Reply

Marsh Posté le 21-07-2004 à 22:24:20    

PS: avec ma solution, 53gh sera avant 5rvst dans mon exemple, non pas parcequ'il est plus court (puisqu'il n'est pas numérique, un tri alphabétique est fait dessus dans mon exemple) mais parceque 3 < r
 
Dans mon exemple, tu auras :
 
5687t
5t
5u396
a58

Reply

Marsh Posté le 21-07-2004 à 22:25:00    

Et les valeurs numériques AVANT, triées par ordre croisant numérique à condition que 10 >= length(champ)
 
Sinon, il me semble que LPAD permet de mettre autrechose de des espaces, à ce moment il faut mettre des '0' à la place, afin d'éviter d'avoir ça :
 
2
01


Message édité par Arjuna le 21-07-2004 à 22:28:22
Reply

Marsh Posté le 21-07-2004 à 22:27:43    

Exact, mauvais exemple de ma part. Prends 6rvst et 53gh.
Pour la raison de l'ordre, suis le lien que j'ai donné.

Reply

Marsh Posté le 21-07-2004 à 22:28:37    

Arjuna a écrit :

Et les valeurs numériques AVANT, triées par ordre croisant numérique à condition que 10 >= length(champ)
 
Sinon, il me semble que LPAD permet de mettre autrechose de des espaces, à ce moment il faut mettre des '0' à la place, afin d'éviter d'avoir ça :
 
 2
01


les 0 placé devant sont ignorés dans le tri naturel.

Reply

Marsh Posté le 21-07-2004 à 22:30:06    

hmm, ok, je vois pour le coup des nombres à l'intérieur d'une chaîne.
 
par contre, je ne vois pas pourquoi 6rvst est devabt 53gh

Reply

Marsh Posté le 21-07-2004 à 22:30:49    

gizmo a écrit :

les 0 placé devant sont ignorés dans le tri naturel.


Justement, avec mon système, pour faire abstraction des 0, il faut en mettre partout, comme ça il ne peuvent plus influer.

Reply

Marsh Posté le 21-07-2004 à 22:31:30    

Arjuna a écrit :

Justement, avec mon système, pour faire abstraction des 0, il faut en mettre partout, comme ça il ne peuvent plus influer.


non, parce qu'il y a une nuance pour départager 01 et 1. Là les 0 comptent.


Message édité par gizmo le 21-07-2004 à 22:31:40
Reply

Marsh Posté le 21-07-2004 à 22:34:14    

mouais
 
m'enfin l'algo me semble asez complexe pour un besion pas forcément aussi strict. a defaut de mieu, je pense que ma dernière solution est la plus proche, et de toute façon, à moins de passer par un PL de tarré, y'a pas moyen de faire mieu (ou alors je tire mon chapeau bien bas)
 
Ma solution permettant de s'approcher un minimum de ce type de tri, elle a au moins le mérite d'etre simple à mettre en oeuvre.
 
Par contre, j'ai ma petite idée sur l'algo pour fraire le truc en PL, mais j'ai pas envie de le poster, il est trop chiant à expliquer (et je ne suis pas certain qu'il marche... Par contre il retourne bien le 6 avant le 53 dans le cas où il est noyé dans une chaîne.


Message édité par Arjuna le 21-07-2004 à 22:36:20
Reply

Marsh Posté le 21-07-2004 à 22:38:13    

Le but de l'algo étant de décomposer chaque chaîne en "bouts" chaine - numérique - chaine - numérique etc.
 
puis trier à la queue leu-leu chaque sous-groupe (en mode alphabétique pour les chaines et numérique pour les nombres)
 
Ca me semble fonctionner correctement, mais je souhaute bon courrage à celui qui veut le faire en PL/SQL, bien que ça ne doive pas être trop complexe à faire...

Reply

Marsh Posté le 21-07-2004 à 22:41:15    

bah oui, le faire en pl, c'est la solution que je lui ai proposé depuis le début, mais spa grave hein ;)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed