it-swarm.com.de

Wie sortiere ich eine VARCHAR-Spalte in SQL Server, die Zahlen enthält?

Ich habe eine VARCHAR Spalte in einem SQL Server 2000 Datenbank, die entweder Buchstaben oder Zahlen enthalten kann. Dies hängt davon ab, wie die Anwendung im Front-End für den Kunden konfiguriert ist.

Wenn es Zahlen enthält, möchte ich, dass es numerisch sortiert wird, z. als "1", "2", "10" anstelle von "1", "10", "2". Felder, die nur Buchstaben oder Buchstaben und Zahlen enthalten (z. B. 'A1'), können wie gewohnt alphabetisch sortiert werden. Dies wäre beispielsweise eine akzeptable Sortierreihenfolge.

1
2
10
A
B
B1

Was ist der beste Weg, um dies zu erreichen?

49
Tim C

Eine mögliche Lösung besteht darin, die numerischen Werte mit einem vorangestellten Zeichen aufzufüllen, sodass alle Zeichenfolgen dieselbe Länge haben.

Hier ist ein Beispiel für diesen Ansatz:

select MyColumn
from MyTable
order by 
    case IsNumeric(MyColumn) 
        when 1 then Replicate('0', 100 - Len(MyColumn)) + MyColumn
        else MyColumn
    end

Das 100 sollte durch die tatsächliche Länge dieser Spalte ersetzt werden.

74
Aleris

Hierfür gibt es einige Möglichkeiten.

Einer wäre

SELECT
 ...
ORDER BY
  CASE 
    WHEN ISNUMERIC(value) = 1 THEN CONVERT(INT, value) 
    ELSE 9999999 -- or something huge
  END,
  value

der erste Teil von ORDER BY konvertiert alles in ein int (mit einem großen Wert für Nicht-Numerik, um das letzte zu sortieren), dann kümmert sich der letzte Teil um die Alphabetik.

Beachten Sie, dass die Leistung dieser Abfrage bei großen Datenmengen wahrscheinlich mindestens mäßig hoch ist.

12
Cowan
SELECT *, CONVERT(int, your_column) AS your_column_int
FROM your_table
ORDER BY your_column_int

ODER

SELECT *, CAST(your_column AS int) AS your_column_int
FROM your_table
ORDER BY your_column_int

Ich denke, beide sind ziemlich portabel.

5
JohnB
select
  Field1, Field2...
from
  Table1
order by
  isnumeric(Field1) desc,
  case when isnumeric(Field1) = 1 then cast(Field1 as int) else null end,
  Field1

Dies gibt Werte in der Reihenfolge zurück, die Sie in Ihrer Frage angegeben haben.

Die Leistung wird bei all dem Casting nicht allzu hoch sein. Daher besteht ein anderer Ansatz darin, der Tabelle, in der Sie eine ganzzahlige Kopie der Daten speichern, eine weitere Spalte hinzuzufügen und erst danach und dann nach der betreffenden Spalte zu sortieren. Dies erfordert natürlich einige Änderungen an der Logik, die Daten in die Tabelle einfügt oder aktualisiert, um beide Spalten zu füllen. Entweder das, oder setzen Sie einen Trigger in die Tabelle, um die zweite Spalte jedes Mal zu füllen, wenn Daten eingefügt oder aktualisiert werden.

5
Luke Bennett

sie können Ihre varchar-Spalte jederzeit in bigint konvertieren, da die Ganzzahl möglicherweise zu kurz ist ...

select cast([yourvarchar] as BIGINT)

sie sollten sich aber immer für Buchstaben interessieren

where ISNUMERIC([yourvarchar] +'e0') = 1

das + 'e0' kommt von http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/isnumeric-isint-isnumber

dies würde zu Ihrer Aussage führen

SELECT
  *
FROM
  Table
ORDER BY
   ISNUMERIC([yourvarchar] +'e0') DESC
 , LEN([yourvarchar]) ASC

in der ersten Sortierspalte wird die Nummer oben angezeigt. die zweite sortiert nach Länge, also werden 10 vor 0001 stehen (was ist dumm ?!)

dies führt zur zweiten Version:

SELECT
      *
    FROM
      Table
    ORDER BY
       ISNUMERIC([yourvarchar] +'e0') DESC
     , RIGHT('00000000000000000000'+[yourvarchar], 20) ASC

die zweite Spalte wird jetzt rechts mit '0' aufgefüllt, sodass bei der natürlichen Sortierung Ganzzahlen mit führenden Nullen (0,01,10,0100 ...) in der richtigen Reihenfolge angezeigt werden (richtig!). Alle Alphas werden jedoch mit '0' erweitert. -chars (Leistung)

so dritte version:

 SELECT
          *
        FROM
          Table
        ORDER BY
           ISNUMERIC([yourvarchar] +'e0') DESC
         , CASE WHEN ISNUMERIC([yourvarchar] +'e0') = 1
                THEN RIGHT('00000000000000000000' + [yourvarchar], 20) ASC
                ELSE LTRIM(RTRIM([yourvarchar]))
           END ASC

jetzt werden Zahlen zuerst mit '0'-Zeichen aufgefüllt (natürlich kann die Länge 20 erhöht werden) - die Zahlen werden richtig sortiert - und Alphas werden nur gekürzt

4
Bernhard

Ich habe es auf sehr einfache Weise gelöst, indem ich dies in den "order" Teil geschrieben habe

ORDER BY (
sr.codice +0
)
ASC

Dies scheint sehr gut zu funktionieren, in der Tat hatte ich die folgende Sortierung:

16079   Customer X 
016082  Customer Y
16413   Customer Z

Also das 0 vor 16082 wird korrekt berücksichtigt.

4
Orz

Das scheint zu funktionieren:

select your_column  
from your_table  
order by   
case when isnumeric(your_column) = 1 then your_column else 999999999 end,  
your_column   
2
Corey Trager

Diese Abfrage ist hilfreich für Sie. In dieser Abfrage ist eine Spalte vom Datentyp varchar nach guter Reihenfolge angeordnet. In dieser Spalte sind die Daten beispielsweise: - G1, G34, G10, G3. Nachdem Sie diese Abfrage ausgeführt haben, werden die folgenden Ergebnisse angezeigt: - G1, G10, G3, G34.

SELECT *,
       (CASE WHEN ISNUMERIC(column_name) = 1 THEN 0 ELSE 1 END) IsNum
FROM table_name 
ORDER BY IsNum, LEN(column_name), column_name;
0
Nitika Chopra

Dies kann Ihnen helfen, ich habe dies versucht, als ich das gleiche Problem bekam.

SELECT * FROM tab ORDER BY IIF(TRY_CAST(val AS INT) IS NULL, 1, 0),TRY_CAST(val AS INT);

0
Dennis
SELECT FIELD FROM TABLE
ORDER BY 
  isnumeric(FIELD) desc, 
  CASE ISNUMERIC(test) 
    WHEN 1 THEN CAST(CAST(test AS MONEY) AS INT)
    ELSE NULL 
  END,
  FIELD

Gemäß dieser Link müssen Sie nach MONEY und dann nach INT umwandeln, um zu vermeiden, dass Sie '$' als Zahl bestellen.

0
Matt Mitchell