Najpierw porządkowanie według określonej wartości pola

92

Mam tabelę z 3 kolumnami:

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

Chcę uporządkować zestaw wyników za pomocą, priorityale najpierw tych wierszy, które mają name=corenawet niższy priorytet. Wynik powinien wyglądać tak

id | name | priority
--------------------
 6 | core  |   4
 2 | core  |   9
 1 | core  |   10
 5 | board |   6
 4 | board |   7
 3 | other |   8
Omid
źródło

Odpowiedzi:

160

Jest też funkcja MySQLFIELD .

Jeśli chcesz kompletne sortowanie dla wszystkich możliwych wartości:

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

Jeśli zależy Ci tylko na tym, aby „rdzeń” był pierwszy, a inne wartości nie mają znaczenia:

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

Jeśli chcesz najpierw posortować według „rdzenia”, a pozostałe pola w normalnej kolejności:

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

Istnieją jednak pewne zastrzeżenia:

Po pierwsze, jestem prawie pewien, że to tylko funkcja mysql - pytanie jest otagowane jako mysql, ale nigdy nie wiadomo.

Po drugie, zwróć uwagę na to, jak FIELD()działa: zwraca indeks wartości ( liczony od jedynek) - w przypadku FIELD(priority, "core")zwraca 1, jeśli wartością jest „rdzeń”. Jeśli wartość pola nie znajduje się na liście, zwraca zero . Dlatego DESCjest to konieczne, chyba że określisz wszystkie możliwe wartości.

Nerdmaster
źródło
5
Po około 5 latach zmieniłem zaakceptowaną odpowiedź na tę, ponieważ jest czystsza i szybsza.
Omid
odpowiednik db2?
Cybermonk
U mnie zadziałało, chciałbym zadać jeszcze jedno pytanie o to, jak sobie poradzić Jeśli kolumna „priorytet” zawiera wartości takie jak np. „Rdzeń ziemi”, „nowa tablica” itp. Tutaj kolumna nie zawiera dokładnej wartości, czy możemy napisać coś w rodzaju %rdzeń%?
Jayanth Suvarna
@JayanthSuvarna: patrząc na dokumentację MySQL FIELD (), jestem prawie pewien, że nie ma sposobu, aby ocenić to jako podciągi, ponieważ każdy argument musi być jakimś ciągiem. Mogą istnieć pewne funkcje manipulujące na ciągach, które mogą pomóc, ale nie jestem pewien.
Nerdmaster
Dzięki stary. Uczyniłeś mój dzień.
BEingprabhU
92

Generalnie możesz to zrobić

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

Szczególnie w MySQL możesz to zrobić

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

Ponieważ wynik porównania w MySQL to albo 0albo 1i możesz sortować według tego wyniku.

juergen d
źródło
1
co tu znaczy 1i co 2oznacza?
Niraj Chauhan
1
Mam około 3000 wierszy do sortowania. W moim przypadku rozwiązanie @ Ayman-Hourieh na stackoverflow.com/questions/958627/… zajmuje połowę czasu w porównaniu z tym rozwiązaniem.
nightlyop
@nightlyop: Dobry. Tylko jedna uwaga: szybsze rozwiązanie jest specyficzne dla MySQL.
juergen d
1i 2to tylko 2 liczby, których używam do sortowania danych. Może 3i 4coś innego.
juergen d
A co z sytuacją, gdy %w WHEREklauzuli jest? Lubisz . . . WHERE name LIKE '%sth%' . . .? stackoverflow.com/questions/41303379/ ...
stos
6

Jednym ze sposobów nadania pierwszeństwa określonym wierszom jest dodanie dużej liczby do ich priorytetu. Możesz to zrobić za pomocą CASEoświadczenia:

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

Demo: http://www.sqlfiddle.com/#!2/753ee/1

mellamokb
źródło
5

To działa dla mnie przy użyciu Postgres 9+:

SELECT *
FROM your_table
ORDER BY name = 'core' DESC, priority DESC
Vojtech Vitek
źródło
Chcesz wyjaśnić -1? Błąd + wersja Postgres?
Vojtech Vitek
3

Oto jeden sposób:

select id, name, priority from table a
order by case when name='core' then -1 else priority end asc, priority asc
Ikar
źródło
1
Czy to nie spowoduje utraty kolejności corerzędów?
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')
meiy arul
źródło
3
Chociaż Twój kod może być odpowiedzią na to pytanie, lepiej podać jakieś wyjaśnienie.
Mehraban
0

Zrób to:

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

Dołączenie +0 oznacza, że:

0, 10, 11, 2, 3, 4

staje się :

0, 2, 3, 4, 10, 11
Madhuka Dilhan
źródło
Ta technika służy do zamiany łańcucha na liczbę. Nie odnosi się do pytania PO. (Jednak nie widząc typu danych priority, nie mogę powiedzieć, czy powinien on być częścią kompletnego rozwiązania.)
Rick James
0

Użyj tego:

SELECT * 
FROM tablename 
ORDER BY priority desc, FIELD(name, "core")
Saquib Azam
źródło