Konwertuj tekst na liczbę w zapytaniu MySQL

138

Czy można zamienić tekst na liczbę w zapytaniu MySQL? Mam kolumnę z identyfikatorem składającym się z nazwy i liczby w formacie „nazwa-numer”. Kolumna ma typ VARCHAR. Chcę posortować wiersze według liczby (wiersze o tej samej nazwie), ale kolumna jest sortowana według kolejności znaków, tj

name-1
name-11
name-12
name-2

Jeśli usunę liczbę, czy mogę zamienić liczbę „varchar” na liczbę „rzeczywistą” i użyć jej do sortowania wierszy? Chciałbym uzyskać następujące zamówienie.

name-1
name-2
name-11
name-12

Nie mogę przedstawić liczby w osobnej kolumnie.

edytowane 2011-05-11 9:32

Znalazłem następujące rozwiązanie ... ORDER BY column * 1. Jeśli nazwa nie będzie zawierała żadnych liczb, to czy warto skorzystać z tego rozwiązania?

czuk
źródło
1
imię to dokładnie imię czy może to być dowolny znak? Mam na myśli: czy to ciąg czterech znaków, czy też prawdziwe imię?
Marco
namemoże być dowolną sekwencją liter.
czuk
1
możliwy duplikat naturalnego sortowania mysql
Shakti Singh

Odpowiedzi:

256

To powinno działać:

SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;
Marco
źródło
1
czy mógłbyś dodać wyjaśnienie i link do dokumentacji?
Angelo Fuchs
Mój ciąg jest podobny do „name-abc12”. Dodanie kodu działa tylko wtedy, gdy początkowe znaki po „-” nie zaczynają się od litery. @Marco Czy możesz mi powiedzieć, jak ignorować litery bez warunku gdzie?
Eduardo
1
@Eduardo moje zapytanie powinno pobrać ciąg znaków po „-” i zamienić go na liczbę (MUSI to być liczba). W twoim przypadku prawdopodobnie
Marco
Wyrażenie regularne @Marco to zrobiło, dziękuję za wskazówkę.
Eduardo
32

Możesz użyć SUBSTRINGi CONVERT:

SELECT stuff
FROM table
WHERE conditions
ORDER BY CONVERT(SUBSTRING(name_column, 6), SIGNED INTEGER);

Gdzie name_columnjest kolumna z wartościami „nazwa-”. SUBSTRINGUsuwa wszystko przed szóstym znaku (czyli „Imieniny” prefix), a następnie CONVERTkonwertuje pozostały do rzeczywistej liczby całkowitej.

AKTUALIZACJA : Biorąc pod uwagę zmieniające się okoliczności w komentarzach (tj. Prefiks może być dowolny), będziesz musiał dodać LOCATEdo miksu:

ORDER BY CONVERT(SUBSTRING(name_column, LOCATE('-', name_column) + 1), SIGNED INTEGER);

To oczywiście zakłada, że ​​nienumeryczny prefiks nie zawiera żadnych myślników, ale odpowiedni komentarz mówi, że:

name może być dowolną sekwencją liter

więc powinno to być bezpieczne założenie.

mu jest za krótkie
źródło
Odpowiadając na mój komentarz, powiedział nam, że nazwa może być dowolną sekwencją znaków, więc nie jestem pewien, czy możesz użyć SUBSTRING(name_column, 6). Wiem, opublikowałeś to, kiedy nam tego nie powiedział ...
Marco
@Marco: Dzięki za ostrzeżenie, dodałem aktualizację, która powinna zająć się nowymi informacjami o prefiksach. Ale tak, Twój SUBSTRING_INDEX jest ładniejszy.
mu jest za krótkie
23

Po prostu użyj CAST,

CAST(column_name AS UNSIGNED)

Typ wyniku rzutowania może mieć jedną z następujących wartości:

BINARY[(N)]
CHAR[(N)]
DATE
DATETIME
DECIMAL[(M[,D])]
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
Sibin John Mattappallil
źródło
14

Możesz użyć CAST (), aby przekonwertować ciąg znaków na int. na przykładSELECT CAST('123' AS INTEGER);

verdesmarald
źródło
15
Czy ta wersja jest specyficzna? Muszę użyć SELECT CAST('123' AS SIGNED INTEGER);lub SELECT CAST('123' AS UNSIGNED INTEGER);sprawić, by działało.
Hobo,
10
SELECT *, CAST(SUBSTRING_INDEX(field, '-', -1) AS UNSIGNED) as num FROM tableName ORDER BY num;
Gaurav
źródło
1
Czy jesteś pewien, że ORDER BY używa num jako liczby bez użycia CONVERT? Nie jestem pewien, ale tak może być… Po prostu zadaję sobie pytanie :)
Marco
4

jeden prosty sposób WYBIERZ „123” + 0

VRK RAO
źródło
Chociaż ten kod może pomóc w rozwiązaniu problemu, dostarczenie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak odpowiada na pytanie, znacznie poprawiłoby jego długoterminową wartość. Proszę edytować swoje odpowiedzi, aby dodać trochę wyjaśnień.
Toby Speight,
To nie odpowiadało na pytanie, ale to była odpowiedź, której szukałem.
Sagar Shah
Twoje rozwiązanie jest najbardziej eleganckie i praktyczne - niestety nie podałeś go w kontekście pytania z konkretnym wyrażeniem dla podanego przykładu - zmodyfikuj je tak, aby było konkretne.
chukko
2

jeśli kluczem podstawowym jest ciąg w formacie takim jak

ABC / EFG / EE / 13/123 (numer kolejny),
tego rodzaju ciąg można łatwo użyć do sortowania za pomocą separatora („/”)

możemy użyć następującego zapytania, aby zamówić tabelę z tego typu kluczem

SELECT * FROM `TABLE_NAME` ORDER BY 
CONVERT(REVERSE(SUBSTRING(REVERSE(`key_column_name`), 1, LOCATE('/', REVERSE(`key_column_name`)) - 1)) , UNSIGNED INTEGER) DESC
Harsha
źródło
0
cast(REGEXP_REPLACE(NameNumber, '[^0-9]', '') as UNSIGNED)
Jayram Kumar
źródło
-5

Ogólny sposób na zrobienie:

SELECT * FROM your_table ORDER BY LENTH(your_column) ASC, your_column ASC
Azzu
źródło