String urutan SQL sebagai angka

144

Saya memiliki nomor yang disimpan sebagai VARCHARdatabase MySQL. Saya tidak dapat membuatnya INTkarena beberapa keadaan tergantung lainnya.

Ini menganggap mereka sebagai karakter bukan sebagai angka saat menyortir.

Dalam database yang saya miliki

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

Di halaman saya itu menunjukkan daftar yang dipesan seperti ini:

1 10 2 3 4 5 6 7 8 9

Bagaimana cara membuatnya tampak diurutkan berdasarkan angka yang naik?

Jamol
sumber
5
Tentunya Anda harus menyimpan data sebagai angka, bukan string.
Oded
@Oded Anda dapat memiliki beberapa data arbitrer (mis. Pengaturan), yang ingin Anda pesan berdasarkan nilai numeriknya hanya dalam kasus yang sangat khusus.
Glutexo
artikel yang sangat menarik - untuk MSSQL tetapi harus relatif serupa untuk MySQL: essentialql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Jawaban:

268

Jika memungkinkan Anda harus mengubah tipe data kolom menjadi angka jika Anda hanya menyimpan angka saja.

Jika Anda tidak dapat melakukannya, ubah nilai kolom Anda menjadi integer secara eksplisit dengan

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

atau secara implisit misalnya dengan operasi matematika yang memaksa konversi menjadi angka

select col from yourtable
order by col + 0

BTW MySQL mengubah string dari kiri ke kanan. Contoh:

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 */
juergen d
sumber
5
order by col * 1 bekerja dengan sempurna. Apa keajaiban di balik ini? Maaf saya tidak profesional jadi ini mungkin pertanyaan konyol tapi Bagaimana * 1 membuatnya berubah menjadi angka?
Jamol
13
MySQL secara otomatis mengubah string menjadi angka untuk membuat perkalian dengan1
juergen d
1
Opsi pertama adalah yang paling tepat, yang kedua memiliki langkah ekstra, tetapi tetap berfungsi.
Manatax
7
dan jika Anda memiliki nomor dan string campuran dan ingin keduanya diurutkan, gunakan "order by col * 1, col"
Hayden Thring
1
@superphonic: Hasilnya adalah decimal.
juergen d
73

Cara lain, tanpa menggunakan satupun cast.

(Untuk orang yang menggunakan JPA 2.0, di mana casting tidak diperbolehkan)

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

EDIT: hanya berfungsi untuk bilangan bulat positif

Velter
sumber
9
ini bagus, itu bekerja dengan kolom yang juga berisi int dan string
Sruit A. Suk
1
Ini tidak akan berfungsi di semua kasus. Di luar kepala, kasing yang tidak akan berfungsi adalah campuran bilangan bulat dengan; angka negatif, angka dengan nol di depan, angka dengan pecahan dan kata dan angka digabungkan.
WonderWorker
3
solusi hebat tanpa jenis casting dan juggling, +1
Maksim Luzik
tampaknya tidak berhasil pada pandangan pertama, tetapi berhasil! Terima kasih!
try2fly.b4ucry
21

Cara lain dan sederhana

ORDER BY ABS(column_name)

Parth Solanki
sumber
18

Kolom yang saya sortir memiliki kombinasi alfa dan numerik, jadi saya menggunakan saran dalam posting ini sebagai titik awal dan menghasilkan ini.

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;

Hasil

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

Semoga ini membantu

Losbear
sumber
1
Anda cukup menggunakan 1 - ISNUMERIC(ID)alih-alih (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)mengubah 0 ke 1 dan sebaliknya.
S. Serpooshan
7

Ini berhasil untuk saya.

select * from tablename
order by cast(columnname as int) asc
Patrick De Guzman
sumber
bisa kamu jelaskan kenapa
Slavik
jawaban paling sederhana, yang melakukan apa yang dibutuhkan, mentransmisikan string ke int, lalu mengurutkan int itu dalam urutan menaik, tidak ada hal yang funky :)
denford mutseriwa
4

Cara lain untuk mengonversi.

Jika Anda memiliki bidang string, Anda dapat mengubahnya atau bagian numeriknya dengan cara berikut: tambahkan nol di depan agar semua string bilangan bulat memiliki panjang yang sama.

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

atau urutkan berdasarkan bagian bidang seperti 'tensymbols13', 'tensymbols1222', dll.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 
shukshin.ivan
sumber
3

Ini akan menangani angka negatif, pecahan, string, semuanya:

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

Saya juga mencari bidang penyortiran yang memiliki awalan huruf. Inilah yang saya temukan solusinya. Ini mungkin membantu yang mencari solusi yang sama.

Nilai Bidang:

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) saya meletakkan 9 karena 9 adalah cara yang cukup bagi saya untuk menahan nilai integer maksimal 9 digit.

Sehingga hasilnya akan menjadi 123456789 123456788 123456787 ... 100 99 ... 2 1

pengguna2400083
sumber
2

Mungkin membantu siapa yang mencari solusi yang sama.

select * from tablename ORDER BY ABS(column_name)
Samir Lakhani
sumber
0

Jika Anda menggunakan AdonisJS dan memiliki ID campuran seperti ABC-202, ABC-201 ..., Anda dapat menggabungkan kueri mentah dengan Query Builder dan menerapkan solusi di atas ( https://stackoverflow.com/a/25061144/4040835 ) sebagai berikut:

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
  )

CATATAN: Dalam baris ini: SUBSTRING(:sortField:,3,15)*1 ${sortDirection},

  1. '3' adalah nomor indeks dari karakter non-numerik terakhir sebelum digit. Jika ID campuran Anda adalah "ABC-123", nomor indeks Anda adalah 4.
  2. '15' digunakan untuk menangkap sebanyak mungkin digit setelah tanda hubung.
  3. '1' melakukan operasi matematika pada substring yang secara efektif melemparkan substring ke angka.

Referensi 1: Anda dapat membaca lebih lanjut tentang pengikatan parameter dalam kueri mentah di sini: https://knexjs.org/#Raw-Bindings Ref 2: Kueri Mentah Adonis: https://adonisjs.com/docs/4.1/query-builder# _raw_queries

Ndianabasi
sumber
-4

Ubah bidang Anda menjadi INT, bukan VARCHAR.

Saya tidak dapat membuat mereka INT karena beberapa keadaan tergantung lainnya.

Kemudian perbaiki dulu keadaan tergantung. Jika tidak, Anda sedang mengatasi masalah mendasar yang sebenarnya. Menggunakan MySQL CAST adalah sebuah opsi, tetapi itu menutupi skema buruk Anda yang harus diperbaiki.

Lembah kecil
sumber