Cara menetapkan pesanan ORDER BY menurut pesanan di mySQL

142

Di MySQL, bagaimana cara menetapkan urutan penyortiran kustom.

Untuk mencoba menjelaskan apa yang ingin saya pertimbangkan tabel ini:

ID  Language    Text
0   ENU         a
0   JPN         b
0   DAN         c       
1   ENU         d
1   JPN         e
1   DAN         f
2   etc...

di sini saya ingin mengembalikan semua baris yang diurutkan berdasarkan Bahasa dan ID naik sehingga Bahasa = ENU yang lebih dulu, kemudian JPN dan terakhir DAN.

Hasilnya harus: a, d, b, e, c, f dll.

Apakah ini mungkin?

Muleskinner
sumber

Jawaban:

275

MySQL memiliki fungsi praktis yang disebut FIELD()sangat baik untuk tugas-tugas seperti ini.

ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID

Namun perhatikan, itu

  1. Itu membuat SQL Anda kurang portabel, karena DBMS lain mungkin tidak memiliki fungsi seperti itu

  2. Ketika daftar bahasa Anda (atau nilai-nilai lain untuk disortir) menjadi lebih lama, lebih baik memiliki tabel terpisah dengan kolom pengurutan untuk mereka, dan bergabung dengan itu ke permintaan Anda untuk memesan.

Mchl
sumber
3
Terima kasih ini sempurna untuk situasi saya di mana saya hanya perlu memesan dengan dua nilai (bahasa utama, misalnya JPN, dan bahasa mundur, misalnya ENU).
Muleskinner
4
Man Anda baru saja menyelamatkan saya menulis ulang di
magento
1
Bagaimana jika Anda punya GROUP BYsebelumnya? Misalnya, nilai pertama yang saya inginkan, muncul di akhir?
Pathros
Masukkan kueri dengan GROUP BYdalam subquery, dan pesan dalam kueri luar
Mchl
1
Bekerja seperti pesona :)
Brane
53

Jika mereka adalah satu-satunya tiga nilai, maka Anda dapat menggunakan sebuah CASEungkapan :

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         END

(Jika mungkin ada nilai-nilai lain, maka Anda mungkin ingin menambahkan beberapa logika ekstra untuk menjaga pemesanan konsisten, misalnya, Anda bisa menambahkan ELSE 4untuk itu CASEekspresi, dan ketertiban maka dengan Languagesendirinya sebagai kriteria pemesanan ketiga:

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         ELSE 4
         END,
         `Language`

)

ruakh
sumber
1
Dan jika ada banyak nilai Bahasa Anda bisa memiliki tabel terpisah yang menyimpan masing-masing Bahasa ditambah kolom urutan sortir dan tautan ke sana
kaj
1
Ini akan dipesan berdasarkan ID terlebih dahulu, menghasilkan a, b, c, d, e, f
piotrm
Terima kasih ini bekerja dengan sempurna - seperti halnya Mchl menjawab yang saya terima karena kelihatannya lebih sederhana
Muleskinner
19

Anda memiliki beberapa opsi begitu saja, yang pertama adalah mengubah Bahasa menjadi ENUM (dengan asumsi ini mungkin, dan Anda hanya mengharapkan beberapa variasi)

Jika Anda menentukannya ENUM('ENU','JPN','DAN')maka ORDER Language ASCakan memesan dalam urutan yang Anda tentukan.

Yang kedua akan melibatkan suatu kasus di suatu tempat, yaitu

SELECT * FROM table
ORDER BY CASE Language
    WHEN 'ENU' THEN 3
    WHEN 'JPN' THEN 2
    WHEN 'DAN' THEN 1
    ELSE 0
END DESC, ID ASC

Dari segi kinerja, metode ENUM akan memberikan hasil yang lebih cepat, tetapi akan lebih merepotkan jika Anda perlu menambahkan lebih banyak bahasa. Opsi ketiga adalah menambahkan tabel normalisasi untuk Bahasa yang mungkin berlebihan dalam hal ini.

Simon di Portal Sekolahku
sumber
Di mana tepatnya Anda mengetik ENUM('ENU','JPN','DAN')?
Pathros
1
@pathros dalam definisi tabel, Anda menetapkannya sebagai ENUM dan bukan VARCHAR dll. Secara internal MySQL menyimpan opsi ENUM dalam urutan tertentu dan mengindeksnya, sehingga ketika memesan dengan kolom ENUM secara khusus, ia akan menggunakan indeks internal alih-alih nilai string (kecuali CAST () digunakan untuk membuatnya kembali ke VARCHAR)
Simon at My School Portal
Tidak END DESC,seharusnya END CASE DESC,?
Istiaque Ahmed
Nggak. Tidak semua CASEperlu END CASE, itu tergantung pada konteks. CASEdalam PROCEDURE memerlukan END CASE( dev.mysql.com/doc/refman/5.5/en/case.html ) namun CASEdalam SELECT tidak memerlukan END CASE, cukup END( dev.mysql.com/doc/refman/5.7/en/… ) - dalam hal ini konteks itu adalah fungsi aliran kontrol.
Simon di Portal My School
1

Untuk kerangka kerja Yii2 kami dapat mencapai dengan mengikuti cara

Project::find()
->orderBy([new Expression('FIELD(pid_is_t_m,2,0,1)'),'task_last_work'=> SORT_ASC])
->all();
Prahlad
sumber