Trier d'abord par valeur de champ spécifique


92

J'ai un tableau avec 3 colonnes:

id | name | priority
--------------------
 1 | core  |   10
 2 | core  |   9
 3 | other |   8
 4 | board |   7
 5 | board |   6
 6 | core  |   4

Je veux commander l'ensemble de résultats en utilisant prioritymais d'abord les lignes qui ont name=coremême si elles ont une priorité inférieure. Le résultat devrait ressembler à ceci

id | name | priority
--------------------
 6 | core  |   4
 2 | core  |   9
 1 | core  |   10
 5 | board |   6
 4 | board |   7
 3 | other |   8

Réponses:


160

Il y a aussi la fonction MySQLFIELD .

Si vous souhaitez un tri complet pour toutes les valeurs possibles:

SELECT id, name, priority
FROM mytable
ORDER BY FIELD(name, "core", "board", "other")

Si vous vous souciez seulement que le "noyau" soit le premier et que les autres valeurs n'ont pas d'importance:

SELECT id, name, priority
FROM mytable
ORDER BY FIELD(name, "core") DESC

Si vous voulez trier d'abord par "noyau", et les autres champs dans l'ordre de tri normal:

SELECT id, name, priority
FROM mytable
ORDER BY FIELD(name, "core") DESC, priority

Il y a cependant quelques mises en garde:

Tout d'abord, je suis à peu près sûr qu'il s'agit d'une fonctionnalité uniquement mysql - la question est étiquetée mysql, mais on ne sait jamais.

Deuxièmement, faites attention à la façon dont FIELD()fonctionne: il renvoie l' index basé sur un de la valeur - dans le cas de FIELD(priority, "core"), il retournera 1 si "core" est la valeur. Si la valeur du champ n'est pas dans la liste, elle renvoie zéro . C'est pourquoi DESCest nécessaire, sauf si vous spécifiez toutes les valeurs possibles.


5
Après environ 5 ans, j'ai changé la réponse acceptée à celle-ci car elle est plus propre et plus rapide.
Omid

équivalent db2?
Cybermonk

Cela a fonctionné pour moi, j'aimerais poser une question de plus sur la façon de gérer Si la colonne 'priority' contient des valeurs comme ex: 'earth core', 'new board', etc. %coeur%?
Jayanth Suvarna

@JayanthSuvarna: en regardant la documentation MySQL FIELD (), je suis presque sûr qu'il n'y a aucun moyen d'évaluer cela comme des sous-chaînes, car chaque argument doit être une sorte de chaîne. Il peut y avoir des fonctions de manipulation de chaînes qui pourraient aider, mais je ne suis pas sûr.
Nerdmaster

Merci mon pote. Tu as fait ma journée.
BEingprabhU

92

Généralement, vous pouvez faire

select * from your_table
order by case when name = 'core' then 1 else 2 end,
         priority 

Surtout dans MySQL, vous pouvez également faire

select * from your_table
order by name <> 'core',
         priority 

Puisque le résultat d'une comparaison dans MySQL est soit 0ou 1et vous pouvez trier par ce résultat.


1
que signifie 1et que 2signifie ici?
Niraj Chauhan

1
J'ai environ 3000 lignes à trier. Dans mon cas, la solution de @ Ayman-Hourieh sur stackoverflow.com/questions/958627/… prend la moitié du temps par rapport à cette solution.
soirée le

@nightlyop: Bien. Une seule remarque: la solution la plus rapide est spécifique à MySQL.
juergen d

1et ne 2sont que 2 nombres que j'utilise pour trier les données. Cela pourrait être 3et 4ou autre chose.
juergen d

Et quand il y en a %dans l' WHEREarticle? Comme . . . WHERE name LIKE '%sth%' . . .? stackoverflow.com/questions/41303379/…
pile

6

Une façon de donner la préférence à des lignes spécifiques consiste à ajouter un grand nombre à leur priorité. Vous pouvez le faire avec une CASEdéclaration:

  select id, name, priority
    from mytable
order by priority + CASE WHEN name='core' THEN 1000 ELSE 0 END desc

Démo: http://www.sqlfiddle.com/#!2/753ee/1


5

Cela fonctionne pour moi avec Postgres 9+:

SELECT *
FROM your_table
ORDER BY name = 'core' DESC, priority DESC

Voulez-vous expliquer -1? Erreur + version Postgres?
Vojtech Vitek

3

Une façon est la suivante:

select id, name, priority from table a
order by case when name='core' then -1 else priority end asc, priority asc

1
Cela ne perdra-t-il pas l'ordre des corelignes?
mellamokb

1
SELECT * FROM cars_new WHERE status = '1' and car_hide !='1' and cname IN ('Executive Car','Saloon','MPV+','MPV5') ORDER BY FIELD(cname, 'Executive Car', 'Saloon','MPV+','mpv5')

3
Bien que votre code puisse être la réponse à la question, il est préférable de fournir des explications à ce sujet.
Mehraban

0

faites ceci:

SELECT * FROM table ORDER BY column `name`+0 ASC

Ajouter le +0 signifie que:

0, 10, 11, 2, 3, 4

devient :

0, 2, 3, 4, 10, 11

Cette technique permet de transformer une chaîne en un nombre. Il ne répond pas à la question du PO. (Cependant, sans voir le type de données de priority, je ne peux pas dire si cela devrait faire partie de la solution complète.)
Rick James

0

Utilisez ceci:

SELECT * 
FROM tablename 
ORDER BY priority desc, FIELD(name, "core")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.