SQL-Auftragszeichenfolge als Nummer


137

Ich habe Nummern VARCHARin einer MySQL-Datenbank gespeichert. Ich kann sie INTaufgrund anderer Umstände nicht herstellen.

Beim Sortieren werden sie als Zeichen und nicht als Zahl verwendet.

In der Datenbank habe ich

1 2 3 4 5 6 7 8 9 10...

Auf meiner Seite wird eine geordnete Liste wie folgt angezeigt:

1 10 2 3 4 5 6 7 8 9

Wie kann ich es nach aufsteigenden Zahlen geordnet erscheinen lassen?


5
Sicherlich hätten Sie die Daten als Zahl anstelle einer Zeichenfolge speichern sollen.
Oded

@Oded Sie können einige beliebige Daten (z. B. Einstellungen) haben, die Sie nur in ganz besonderen Fällen nach ihrem numerischen Wert sortieren möchten.
Glutexo

Sehr interessanter Artikel - ist für MSSQL, sollte aber für MySQL relativ ähnlich sein: essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Antworten:


256

Wenn möglich, sollten Sie den Datentyp der Spalte in eine Zahl ändern, wenn Sie ohnehin nur Zahlen speichern.

Wenn Sie das nicht können, wandeln Sie Ihren Spaltenwert integer explizit in einen mit um

select col from yourtable
order by cast(col as unsigned)

oder implizit zum Beispiel mit einer mathematischen Operation, die eine Umwandlung in eine Zahl erzwingt

select col from yourtable
order by col + 0

Übrigens konvertiert MySQL Zeichenfolgen von links nach rechts. Beispiele:

string value  |  integer value after conversion
--------------+--------------------------------
'1'           |  1
'ABC'         |  0   /* the string does not contain a number, so the result is 0 */
'123miles'    |  123 
'$123'        |  0   /* the left side of the string does not start with a number */

3
Bestellung von col * 1 funktioniert perfekt. Was ist die Magie dahinter? Tut mir leid, dass ich nicht professionell bin, also könnte dies eine dumme Frage sein, aber wie * 1 ändert sich die Zahl?
Jamol

12
MySQL konvertiert die Zeichenfolge automatisch in eine Zahl, um die Multiplikation mit1
juergen

1
Die erste Option ist am besten geeignet, die zweite hat einen zusätzlichen Schritt, funktioniert aber trotzdem.
Manatax

5
und wenn Sie Zeichenfolge und Nummer gemischt haben und beide sortiert haben möchten, verwenden Sie "order by col * 1, col"
Hayden Thring

1
@superphonic: Das Ergebnis wird sein decimal.
Jürgen d

70

Ein anderer Weg, ohne eine einzige Besetzung zu verwenden.

(Für Leute, die JPA 2.0 verwenden, wo kein Casting erlaubt ist)

select col from yourtable
order by length(col),col

BEARBEITEN: funktioniert nur für positive ganze Zahlen


9
Dies ist eine gute, die mit Spalte gearbeitet hat, die auch sowohl int als auch string enthält
Sruit A.Suk

1
Dies funktioniert nicht in allen Fällen. Auf den ersten Blick sind Fälle, die nicht funktionieren, eine Mischung aus ganzen Zahlen mit; negative Zahlen, Zahlen mit führenden Nullen, Zahlen mit Brüchen und Wörter und Zahlen kombiniert.
WonderWorker

3
Tolle Lösung ohne Casting und Jonglieren, +1
Maksim Luzik

schien auf den ersten Blick nicht zu funktionieren, aber es hat funktioniert! Danke dir!
try2fly.b4ucry


17

Die Spalte, mit der ich sortiere, enthält eine beliebige Kombination aus Alpha und Numerisch. Daher habe ich die Vorschläge in diesem Beitrag als Ausgangspunkt verwendet und mir diese ausgedacht.

DECLARE @tmp TABLE (ID VARCHAR(50));
INSERT INTO @tmp VALUES ('XYZ300');
INSERT INTO @tmp VALUES ('XYZ1002');
INSERT INTO @tmp VALUES ('106');
INSERT INTO @tmp VALUES ('206');
INSERT INTO @tmp VALUES ('1002');
INSERT INTO @tmp VALUES ('J206');
INSERT INTO @tmp VALUES ('J1002');

SELECT ID, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END) IsNum
FROM @tmp
ORDER BY IsNum, LEN(ID), ID;

Ergebnisse

ID
------------------------
106
206
1002
J206
J1002
XYZ300
XYZ1002

Hoffe das hilft


Sie können einfach 1 - ISNUMERIC(ID)anstelle von verwenden (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END), um 0 in 1 zu ändern und umgekehrt.
Serpooshan

7

Das funktioniert bei mir.

select * from tablename
order by cast(columnname as int) asc

kannst du erklären warum?
Slavik

Die einfachste Antwort, die genau das tut, was benötigt wird, ist, die Zeichenfolge in ein Int
umzuwandeln

4

Ein anderer Weg zu konvertieren.

Wenn Sie ein Zeichenfolgenfeld haben, können Sie es oder seinen numerischen Teil folgendermaßen transformieren: Fügen Sie führende Nullen hinzu, damit alle ganzzahligen Zeichenfolgen gleich lang sind.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( stringfield ) ) , stringfield ) 

oder bestellen Sie nach einem Teil eines Feldes etwas wie 'tensymbols13', 'tensymbols1222' usw.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 

2

Ich habe auch nach Sortierfeldern mit Buchstabenpräfix gesucht. Hier ist, was ich die Lösung herausgefunden habe. Dies könnte helfen, wer nach der gleichen Lösung sucht.

Feldwerte:

FL01,FL02,FL03,FL04,FL05,...FL100,...FL123456789

select SUBSTRING(field,3,9) as field from table order by SUBSTRING(field,3,10)*1 desc

SUBSTRING(field,3,9) Ich setze 9, weil 9 für mich ausreichend ist, um maximal 9-stellige Ganzzahlwerte zu halten.

Das Ergebnis ist also 123456789 123456788 123456787 ... 100 99 ... 2 1


2

Dies behandelt negative Zahlen, Brüche, Zeichenfolgen, alles:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;

2

Es könnte hilfreich sein, wer nach der gleichen Lösung sucht.

select * from tablename ORDER BY ABS(column_name)

0

Wenn Sie AdonisJS verwenden und gemischte IDs wie ABC-202, ABC-201 ... haben, können Sie Rohabfragen mit Query Builder kombinieren und die obige Lösung implementieren ( https://stackoverflow.com/a/25061144/4040835 ). wie folgt:

const sortField =
  'membership_id'
const sortDirection =
  'asc'
const subquery = UserProfile.query()
  .select(
    'user_profiles.id',
    'user_profiles.user_id',
    'user_profiles.membership_id',
    'user_profiles.first_name',
    'user_profiles.middle_name',
    'user_profiles.last_name',
    'user_profiles.mobile_number',
    'countries.citizenship',
    'states.name as state_of_origin',
    'user_profiles.gender',
    'user_profiles.created_at',
    'user_profiles.updated_at'
  )
  .leftJoin(
    'users',
    'user_profiles.user_id',
    'users.id'
  )
  .leftJoin(
    'countries',
    'user_profiles.nationality',
    'countries.id'
  )
  .leftJoin(
    'states',
    'user_profiles.state_of_origin',
    'states.id'
  )
  .orderByRaw(
    `SUBSTRING(:sortField:,3,15)*1 ${sortDirection}`,
    {
      sortField: sortField,
    }
  )
  .paginate(
    page,
    per_page
  )

HINWEISE: In dieser Zeile : SUBSTRING(:sortField:,3,15)*1 ${sortDirection},

  1. '3' steht für die Indexnummer des letzten nicht numerischen Zeichens vor den Ziffern. Wenn Ihre gemischte ID "ABC-123" ist, lautet Ihre Indexnummer 4.
  2. '15' wird verwendet, um nach dem Bindestrich so viele Ziffern wie möglich abzufangen.
  3. '1' führt eine mathematische Operation an der Teilzeichenfolge durch, die die Teilzeichenfolge effektiv in eine Zahl umwandelt.

Ref. 1: Weitere Informationen zu Parameterbindungen in Rohabfragen finden Sie hier: https://knexjs.org/#Raw-Bindings Ref. 2: Adonis-Rohabfragen: https://adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

Ändern Sie Ihr Feld so, dass es INT anstelle von VARCHAR ist.

Ich kann sie aufgrund anderer Umstände nicht INT machen.

Beheben Sie dann zuerst die entsprechenden Umstände. Andernfalls arbeiten Sie an dem eigentlichen zugrunde liegenden Problem. Die Verwendung eines MySQL CAST ist eine Option, maskiert jedoch Ihr fehlerhaftes Schema, das behoben werden sollte.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.