6
votes

Oracle 10G SQL tri de Varchar2

J'ai un problème de tri avec Oracle 10G. Je ne sais pas si cela est spécifique à 10g ou non.

J'ai le tableau suivant: p> xxx pré>

Effectuer le nom générique Sélectionnez le nom de table_name Order by 1 Code> Produit: P>

A.1
A.2
A.3
A.4
A.5
A.5.1
A.5.2
A.5.3
A.5.10
A.5.10.1


0 commentaires

5 Réponses :


1
votes

Ce qui suit peut vous donner une idée de quoi faire. Pour commander des valeurs du formulaire "A.", vous pouvez commander par la longueur de l'expression suivie de l'expression. Ainsi, A.1 et A.2 sont avant A.10, car leur longueur est plus courte.

Vous pouvez étendre ceci, avec une commande de la manière suivante: xxx


3 commentaires

Je ne suis pas sûr de suivre la logique du code. Y a-t-il une parenthèse manquante ou constitue le substrateur ultérieur, LEN, SUBSTR dans la première déclaration LEN?


C'est une assez bonne solution, mais elle gère seulement une quantité limitée de points.


@ Luke101. . . Le but de la "..." est d'indiquer que le code peut être étendu à l'aide de la même structure que les autres lignes.



0
votes

Voici un moyen de le faire. Je ne dis pas que c'est le seul ou même le meilleur moyen, mais c'est A STRAND> WAY:

SELECT ID,
       NAME
FROM
  (SELECT ID, NAME,
       INSTR(NAME, '.', 1, 1) AS FIRST_DOT_INDEX,
       INSTR(NAME, '.', 1, 2) AS SECOND_DOT_INDEX,
       INSTR(NAME, '.', 1, 3) AS THIRD_DOT_INDEX,
       INSTR(NAME, '.', 1, 4) AS FOURTH_DOT_INDEX
     FROM test_table)
ORDER BY SUBSTR(NAME, 1, FIRST_DOT_INDEX-1),
         TO_NUMBER(SUBSTR(NAME, FIRST_DOT_INDEX+1, (CASE WHEN SECOND_DOT_INDEX>0
                                                      THEN SECOND_DOT_INDEX-1
                                                      ELSE LENGTH(NAME)
                                                    END - FIRST_DOT_INDEX))),
         TO_NUMBER(CASE WHEN SECOND_DOT_INDEX = 0 AND THIRD_DOT_INDEX = 0
                     THEN '0'
                     ELSE SUBSTR(NAME, SECOND_DOT_INDEX+1, (CASE WHEN THIRD_DOT_INDEX>0
                                                              THEN THIRD_DOT_INDEX-1
                                                              ELSE LENGTH(NAME)
                                                            END - SECOND_DOT_INDEX)) 
                   END),
         TO_NUMBER(CASE WHEN THIRD_DOT_INDEX > 0
                     THEN SUBSTR(NAME, THIRD_DOT_INDEX+1, LENGTH(NAME) - THIRD_DOT_INDEX)
                     ELSE '0'
                   END);


1 commentaires

Ceci compte-t-il que j'ai des longueurs de caractères et de sections de points?



2
votes

Essayez ceci xxx

ici est un violon


2 commentaires

Cela fonctionne définitivement. Pouvez-vous expliquer ce qui se passe? En outre, c'est une requête lourde qui prend beaucoup de temps pour générer. Est-ce que c'est à cause de l'avec / remplacer ou la concaténation dans l'ordre par? Je vous remercie.


Tout d'abord, il en fait un XML (pas vraiment nécessaire, peut être fait avec des substrateurs et destrs aussi - en réalité, cela peut coûter la performance). Ensuite, il faut chaque noeud (une partie entre points) et les pads avec des zéros à être de haute longueur (disons 5). Maintenant, il peut être trié



0
votes

Utilisation de Regex peut résoudre votre problème,

select *
from new_table
  order by to_number(regexp_replace(name,'[[:alpha:].]*'));


2 commentaires

Cette solution ne triera pas A.5.11 avant A.5.10.1


Ce type de fonctionne, mais les trie en fonction de la longueur de la chaîne d'abord, puis dans le bon ordre.



0
votes

Ma question a été répondue dans un autre poste que j'ai posté pour un problème similaire mais non liée. XXX

Grâce à ACHEONG87 pour la solution. Oracle SQL Regexp_replace Correspondant à


0 commentaires