MySQL - ORDER BY nilai dalam IN ()

107

Saya berharap untuk mengurutkan item yang dikembalikan dalam kueri berikut dengan urutan yang mereka masukkan ke dalam fungsi IN () .

MEMASUKKAN:

SELECT id, name FROM mytable WHERE name IN ('B', 'A', 'D', 'E', 'C');

KELUARAN:

|   id   |   name  |
^--------^---------^
|   5    |   B     |
|   6    |   B     |
|   1    |   D     |
|   15   |   E     |
|   17   |   E     |
|   9    |   C     |
|   18   |   C     |

Ada ide?

Matt
sumber

Jawaban:

231
SELECT id, name
FROM mytable
WHERE name IN ('B', 'A', 'D', 'E', 'C')
ORDER BY FIELD(name, 'B', 'A', 'D', 'E', 'C')

Fungsi FIELD mengembalikan posisi string pertama dalam daftar string yang tersisa.

Namun, jauh lebih baik dari segi kinerja untuk memiliki kolom terindeks yang mewakili urutan sortir Anda, lalu urutkan menurut kolom ini.

Ayman Hourieh
sumber
9
@ Vladimir - ya, ini khusus MySQL. Pertanyaan tersebut memiliki tag mysql.
Ayman Hourieh
Bagus, pengganti fungsi "decode" Oracle setelah saklar DB.
Martin Lyne
7
Cermat. Nilai properti apa pun yang tidak diketahui (tidak ada dalam daftar) akan didahulukan daripada nilai yang diketahui, yaitu FIELD(letter, 'A', 'C'), daftar akan mengembalikan entri dengan huruf B terlebih dahulu (dengan asumsi satu set rekaman dengan A | B | Cnilai). Untuk menghindarinya, balikkan daftar dan gunakan DESC, mis FIELD(letter, 'C', 'A') DESC.
Gajus
Bagaimana cara mencapai ini di SQL server.
pengguna123456
29

Pilihan lain dari sini: http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html

select * 
from tablename 
order by priority='High' DESC, priority='Medium' DESC, priority='Low" DESC;

Jadi dalam kasus Anda (belum teruji) akan

SELECT id, name
FROM mytable
WHERE name IN ('B', 'A', 'D', 'E', 'C')
ORDER BY name = 'B', name = 'A', name = 'D', name =  'E', name = 'C';

Bergantung pada apa yang Anda lakukan, saya merasa ini agak aneh tetapi selalu berhasil setelah sedikit bermain dengannya.

joedevon
sumber
Ini mungkin lebih baik daripada menggunakan fungsi field () sebagai jawaban lain yang disarankan karena menggunakan field () akan menghalangi penggunaan indeks, tetapi memiliki kesempatan untuk menggunakan indeks menggunakan metode ini (meskipun tidak yakin seberapa baik ia menggunakan indeks)
ʞɔıu
4

Cobalah sesuatu seperti

... ORDER BY (CASE NAME WHEN 'B' THEN 0 WHEN 'A' THEN 1 WHEN ...
Vladimir Dyuzhev
sumber
3

Mungkin ini bisa membantu seseorang (p_CustomerId diteruskan dalam SP):

SELECT CompanyAccountId, CompanyName
FROM account
LEFT JOIN customer where CompanyAccountId = customer.AccountId
GROUP BY CompanyAccountId
ORDER BY CASE WHEN CompanyAccountId IN (SELECT AccountId 
                                          FROM customer
                                          WHERE customerid= p_CustomerId) 
                 THEN 0
                 ELSE 1
          END, CompanyName;

Deskripsi: Saya ingin menampilkan daftar akun. Di sini saya mengirimkan id pelanggan di sp. Sekarang ini akan mencantumkan nama akun dengan akun yang ditautkan ke pelanggan yang ditampilkan di atas diikuti oleh akun lain dalam urutan abjad.

Hun
sumber
2

Anda memerlukan kolom lain (numerik) di tabel Anda, di mana Anda menentukan urutan sortir. Klausa IN tidak berfungsi seperti ini.

B - 1
A - 2
D - 3
E - 4
C - 5
Robert Harvey
sumber
2
Urutan yang diinginkan mungkin per kueri.
Vladimir Dyuzhev
0

gunakan saja

order by INSTR( ',B,C,D,A,' ,  concat(',' , `field`, ',' ) )

hindari situasi seperti itu

 INSTR('1,2,3,11' ,`field`) 

akan diakhiri dengan baris hasil tidak berurutan: 1 dan 11 alternatif

PercyQQ
sumber