MySQL - ORDER BY valeurs dans IN ()

107

J'espère trier les éléments retournés dans la requête suivante par l'ordre dans lequel ils sont entrés dans la fonction IN () .

CONTRIBUTION:

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

PRODUCTION:

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

Des idées?

Mat
la source

Réponses:

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

La fonction FIELD renvoie la position de la première chaîne dans la liste de chaînes restante.

Cependant, il est préférable, en termes de performances, d'avoir une colonne indexée qui représente votre ordre de tri, puis de trier par cette colonne.

Ayman Hourieh
la source
9
@Vladimir - oui, c'est spécifique à MySQL. La question a la balise mysql.
Ayman Hourieh le
Excellent, remplacement de la fonction "décoder" d'Oracle après le changement de base de données.
Martin Lyne
7
Prudent. Toute valeur de propriété inconnue (ne FIELD(letter, 'A', 'C')figurant pas dans la liste) prévaudra sur les valeurs connues, c'est-à-dire que la liste retournera d'abord les entrées avec la lettre B en premier (en supposant un ensemble d'enregistrements avec des A | B | Cvaleurs). Pour éviter cela, inversez la liste et utilisez DESC, ie FIELD(letter, 'C', 'A') DESC.
Gajus
Comment puis-je y parvenir dans le serveur SQL.
user123456
29

Une autre option d'ici: 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;

Donc, dans votre cas (non testé) serait

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

En fonction de ce que vous faites, je l'ai trouvé un peu bizarre mais je l'ai toujours fait fonctionner après avoir joué un peu avec.

Joedevon
la source
Cela peut être mieux que d'utiliser la fonction field () comme une autre réponse suggérée car l'utilisation de field () empêchera l'utilisation de l'index, mais il a une chance d'utiliser un index en utilisant cette méthode (pas sûr dans quelle mesure il pourrait utiliser l'index, cependant)
ʞɔıu
4

Essayez quelque chose comme

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

Peut-être que cela peut aider quelqu'un (p_CustomerId est passé dans 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;

Description: je souhaite afficher la liste des comptes. Ici, je passe un identifiant client dans sp. Maintenant, il répertorie les noms de compte avec des comptes liés à ces clients sont affichés en haut, suivis des autres comptes par ordre alphabétique.

Hun
la source
2

Vous avez besoin d'une autre colonne (numérique) dans votre tableau, dans laquelle vous spécifiez l'ordre de tri. La clause IN ne fonctionne pas de cette façon.

B - 1
A - 2
D - 3
E - 4
C - 5
Robert Harvey
la source
2
L'ordre souhaité peut être par requête.
Vladimir Dyuzhev
0

juste utiliser

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

éviter la situation comme

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

se terminera par une ligne de résultat non ordonnée: 1 et 11 alternant

PercyQQ
la source