6 Stimmen

Oracle 10g SQL-Sortierung VARCHAR2

Ich habe ein Sortierproblem mit Oracle 10g. Ich bin nicht sicher, ob es spezifisch für 10g ist oder nicht.

Ich habe die folgende Tabelle:

ID  NAME
 1  A.1
 2  A.3
 3  A.4
 4  A.5
 5  A.2
 6  A.5.1
 7  A.5.2
 8  A.5.10
 9  A.5.10.1
10  A.5.3

Ausführen der generischen SELECT NAME FROM table_name ORDER BY 1 produziert:

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

Ich möchte, dass korrekt sortiert wird, wenn diese Abschnitte Zahlen größer als 9 haben, etwa so:

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

Ich habe viel mehr Zahleneinträge als diese mit unterschiedlichen Längen und viele Abschnitte mit Zahlensegmenten größer als 10. Ich habe versucht, mit regexp_replace() in der order by-Klausel herumzuspielen, aber ich hatte kein Glück. Für jede Hilfe wäre ich Ihnen sehr dankbar.

2voto

A.B.Cade Punkte 16565

Versuchen Sie dies

WITH t AS
(
  SELECT id,name,
  xmltype('<r><c>' ||replace(NAME, '.', '</c><c>')||'</c></r>') AS xmlname
  FROM table1
)

SELECT name ,id
FROM t
ORDER BY lpad(extract(xmlname,'//c[1]/text()').getstringval(), 5, '0')
||lpad(extract(xmlname,'//c[2]/text()').getstringval(), 5, '0')
||lpad(extract(xmlname,'//c[3]/text()').getstringval(), 5, '0')
||lpad(extract(xmlname,'//c[4]/text()').getstringval(), 5, '0')

Hier ist eine Fiedel

1voto

Gordon Linoff Punkte 1198148

Die folgenden Hinweise können Ihnen eine Vorstellung davon vermitteln, was zu tun ist. Um Werte der Form "A." zu ordnen, können Sie nach der Länge des Ausdrucks, gefolgt von dem Ausdruck, ordnen. So stehen A.1 und A.2 vor A.10, weil ihre Länge kürzer ist.

Sie können dies erweitern, indem Sie eine Bestellung wie folgt aufgeben:

order by substr(val, 1, instr('.')),
         len(substr(val, 1, instr('.', 1, 2)),
         substr(val, 1, instr('.', 1, 2)),
         len(substr(val, 1, instr('.', 1, 3)),
         substr(val, 1, instr('.', 1, 3)) . . .

0voto

Hier ist eine Möglichkeit, dies zu tun. Ich sage nicht, dass dies der einzige oder sogar der beste Weg ist, aber es ist A Weise:

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);

Teilen und genießen.

0voto

planben Punkte 660

Die Verwendung von regex kann Ihr Problem lösen,

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

Was diese Abfrage bedeutet, dass ich die Alpha-Zeichen + das '.'-Zeichen aus der Spalte NAME ersetze, in eine Zahl umwandle und dann sortiere.

Ich hoffe, das war hilfreich, viel Spaß!

0voto

Gabe Ortiz Punkte 147

Meine Frage wurde eigentlich in einem anderen Beitrag beantwortet, den ich zu einem ähnlichen, aber nicht verwandten Problem geschrieben habe.

Oracle SQL doesn't support lookaround assertions, which would be useful for this case:

s/([0-9](?<![0-9]))/0\1/g

You'll have to use at least two replacements:

REGEXP_REPLACE(REGEXP_REPLACE(col, '([0-9]+)', '0\1'), '0([0-9]{2})', '\1')`

Vielen Dank an acheong87 für die Lösung. Oracle SQL Regexp_replace-Abgleich

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X