MySQL - ORDER BY valori all'interno di IN ()


107

Spero di ordinare gli elementi restituiti nella seguente query in base all'ordine in cui sono stati inseriti nella funzione IN () .

INGRESSO:

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

PRODUZIONE:

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

Qualche idea?

Risposte:


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

La funzione FIELD restituisce la posizione della prima stringa nell'elenco di stringhe rimanente.

Tuttavia, è molto meglio in termini di prestazioni avere una colonna indicizzata che rappresenta il proprio ordinamento, quindi ordinare in base a questa colonna.


9
@Vladimir - sì, è specifico per MySQL. La domanda ha il tag mysql.
Ayman Hourieh

Ottimo, sostituto della funzione "decodifica" di Oracle dopo il cambio di DB.
Martin Lyne

7
Attento. Qualsiasi valore di proprietà sconosciuto (non nell'elenco) avrà la precedenza sui valori noti, ovvero FIELD(letter, 'A', 'C')l'elenco restituirà prima le voci con prima la lettera B (assumendo un insieme di record con A | B | Cvalori). Per evitare ciò, invertire l'elenco e utilizzare DESC, ad es FIELD(letter, 'C', 'A') DESC.
Gajus

Come ottengo questo in SQL Server.
user123456

29

Un'altra opzione da qui: 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;

Quindi nel tuo caso (non testato) sarebbe

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';

A seconda di cosa stai facendo, l'ho trovato un po 'bizzarro, ma l'ho sempre fatto funzionare dopo averci giocato un po'.


Questo potrebbe essere meglio dell'utilizzo della funzione field () come un'altra risposta suggerita perché l'uso di field () precluderà l'utilizzo dell'indice, ma ha la possibilità di usare un indice usando questo metodo (non sono sicuro di quanto bene potrebbe usare l'indice, però)
ʞɔıu

4

Prova qualcosa di simile

... ORDER BY (CASE NAME WHEN 'B' THEN 0 WHEN 'A' THEN 1 WHEN ...

3

Può essere che questo possa aiutare qualcuno (p_CustomerId viene passato in 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;

Descrizione: voglio mostrare l'elenco degli account. Qui sto passando un ID cliente in sp. Ora elencherà i nomi degli account con gli account collegati a cui i clienti sono mostrati in alto, seguiti da altri account in ordine alfabetico.


2

Hai bisogno di un'altra colonna (numerica) nella tua tabella, in cui specifichi l'ordinamento. La clausola IN non funziona in questo modo.

B - 1
A - 2
D - 3
E - 4
C - 5

2
L'ordine desiderato può essere per query.
Vladimir Dyuzhev

0

basta usare

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

evitare la situazione come

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

finirà con la riga dei risultati non ordinata: 1 e 11 alternati

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.