Як визначити користувацький ЗАМОВЛЕННЯ ДО порядку в mySQL


143

Як у MySQL визначити спеціальний порядок сортування.

Спробуйте пояснити, що я хочу розглянути в цій таблиці:

ID  Language    Text
0   ENU         a
0   JPN         b
0   DAN         c       
1   ENU         d
1   JPN         e
1   DAN         f
2   etc...

тут я хочу повернути всі рядки, відсортовані за мовою та зростаючим ідентифікатором, щоб спочатку з'явився Language = ENU, потім JPN та нарешті DAN.

Результат повинен бути: a, d, b, e, c, f і т.д.

Це навіть можливо?

Відповіді:


276

MySQL має зручну функцію під назвою, FIELD()яка відмінно підходить для таких завдань.

ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID

Зауважте, що

  1. Це робить ваш SQL менш портативним, оскільки інші СУБД можуть не мати такої функції

  2. Коли ваш список мов (або інших значень для сортування) стає набагато довшим, краще мати окрему таблицю з стовпцем для їх сортування та приєднати її до запитів для замовлення.


3
Дякую, це ідеально для моєї ситуації, коли мені просто потрібно замовити два значення (основну мову, наприклад JPN, та резервну мову, наприклад ENU).
Muleskinner

4
Людина, ти щойно врятував мені переписання в
магенто

1
Що робити, якщо у вас є GROUP BYраніше? Наприклад, перше значення, яке я хочу, з’являється в кінці?
Патрос

Поставте запит GROUP BYу підзапит і замовляйте його у зовнішньому запиті
Mchl

1
Працюй як шарм :)
Бран

53

Якщо тільки ці три значення, то ви можете використовувати в CASEвираз :

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         END

(Якщо можуть бути інші значення, ви можете додати додаткову логіку для збереження послідовності впорядкування; наприклад, ви можете додати ELSE 4до цього CASEвиразу, а потім упорядкувати Languageсебе як критерій третього порядку:

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         ELSE 4
         END,
         `Language`

)


1
І якщо є багато значень мови, у вас може бути окрема таблиця, де зберігається кожна мова плюс стовпець порядку сортування та посилання на це
kaj

1
Це впорядкується спочатку за ідентифікатором, в результаті чого a, b, c, d, e, f
piotrm

Дякую, це прекрасно працює - як і відповів Мхл, який я прийняв, як це виглядає простіше
Muleskinner

19

У вас є пара варіантів на перший погляд, перший - змінити мову на ENUM (якщо припустити, що це можливо, і ви очікуєте лише декількох варіантів)

Якщо ви вкажете його як ENUM('ENU','JPN','DAN')тоді, ORDER Language ASCбудете впорядковувати у визначеному вами порядку.

Друга залучатиме десь справу, тобто

SELECT * FROM table
ORDER BY CASE Language
    WHEN 'ENU' THEN 3
    WHEN 'JPN' THEN 2
    WHEN 'DAN' THEN 1
    ELSE 0
END DESC, ID ASC

Ефективний метод ENUM поверне більш швидкі результати, але будьте більше клопоту, якщо вам потрібно додати більше мов. Третім варіантом було б додати таблицю нормалізації для Мов, однак, можливо, в цьому випадку зайва кількість.


Де саме ви набираєте ENUM('ENU','JPN','DAN')?
Патрос

1
@pathros у визначенні таблиці ви вказуєте його як ENUM замість VARCHAR тощо. Внутрішньо MySQL зберігає параметри ENUM у визначеному порядку та індексує їх, тому при замовленні в стовпці ENUM спеціально він використовуватиме цей внутрішній індекс замість значення рядка (якщо CAST () не використовується для повернення його до VARCHAR)
Саймон на порталі "Моя школа"

Не повинно END DESC,бути END CASE DESC,?
Істіак Ахмед

Ні. Не всім CASEпотрібно END CASE, це залежить від контексту. CASEв рамках ПРОЦЕДУРИ вимагають END CASE( dev.mysql.com/doc/refman/5.5/en/case.html ), проте CASEв межах SELECT не потрібно END CASE, просто END( dev.mysql.com/doc/refman/5.7/uk/… ) - у цьому контекст - це функція управління потоком.
Саймон на порталі "Моя школа"

1

Для системи Yii2 ми досягаємо наступного способу

Project::find()
->orderBy([new Expression('FIELD(pid_is_t_m,2,0,1)'),'task_last_work'=> SORT_ASC])
->all();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.