MySQL Порядок за номером, Нулі останні


280

В даний час я виконую дуже базовий OrderBy у своїй заяві.

SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC

Проблема в цьому полягає в тому, що записи NULL для "позиції" трактуються як 0. Тому всі записи з позицією NULL з'являються перед записами 1,2,3,4. наприклад:

NULL, NULL, NULL, 1, 2, 3, 4

Чи є спосіб досягти такого впорядкування:

1, 2, 3, 4, NULL, NULL, NULL.

8
Ви повинні переглянути відповідь користувача1052645. Це простіше, не вимагає знань про максимальні значення та може бути швидшим (якщо припустити, що вираз може бути швидшим, ніж виклик функції).
— Стів Клей

Відповіді:


567

У MySQL є незадокументований синтаксис для впорядкування останніх нулів. Поставте знак мінус (-) перед назвою стовпця та переключіть ASC на DESC:

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC

По суті, обернено position DESCрозміщення значень NULL останньою, але інакше такою ж, як position ASC.

Хороший посилання тут http://troels.arvin.dk/db/rdbms#select-order_by


79
Це недокументоване, - col_nameце вираз ( 0 - col_name), який приймає пункт ORDER BY. Звичайно, це працює лише для числових стовпців.
— Стів Клей

7
Хороший. Працює dateі для timeколонок теж! (MySQL 5.5). Я здогадуюсь (я лінивий перевірити), він працює для всіх стовпців, що нагадують число (часова мітка, флоат ...).
— Мартін

6
@koral: це простий (і корисний) математичний вираз, який змінює порядок, він не буде вилучений, якщо сама мова різко не зміниться.
— Белл

11
Як підказують коментарі, він працює для числових, стовпців дати та часу? Але, що з варчаром? Чи можна його застосовувати і для варчара? Я спробував застосувати його до полів varchar, але порядок здається іншим, ніж у використанні ASC або DESC.
— Суміт Дезай

9
Чи не завадить це використовувати можливий індекс для замовлення за стовпцями?
— Тарсіс

305

Я вважаю, що це здебільшого хороше рішення:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;

6
Без переосмислення порядку за роботами: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
— Марсал Хуан

5
Це краще рішення.
— Rok Kralj

4
Прийняте рішення не працює з TIMESTAMP в postgresql 9.3. Це рішення робить ...
— калу

2
Прикро, MySQL не буде використовувати індекс поля, коли ви додасте isnull (поле) до порядку за допомогою пункту (при використанні ліміту).
— Баррі Келлі

3
@kalu: У PostgreSQL значення NULL сортуються останніми у порядку зростання (і спочатку у порядку зменшення). І ви скоріше використовуєте стандартний пункт SQLNULLS LAST | NULLS FIRSTперевернути його замість обхідних шляхів.
— Ервін Брандстетер

23

Щось на зразок

SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC

Замініть 999999999 рівнем максимального значення для поля


3
Це рішення є крихким і може призвести до
— Дмитро Богданович

20

НУЛЬНИЙ ОСТАННІЙ

SELECT * FROM table_name ORDER BY id IS NULL, id ASC

4

Ви можете поміняти місцями NULL з іншим значенням, щоб сортувати їх спочатку (наприклад, 0 або -1) або останній (велика кількість чи літера) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC

Це не вирішить проблему, оскільки індекс, на який посилається ORDER BY, не вплине заміною значень у операторі SELECT і, таким чином, не виправить впорядкування. Також перевірте функцію COALESCE, яка функціонально еквівалентна вашому використанню функції IF.
— визначається

Якщо ви псевдоніміть оператор IF належним чином, рядки впорядковуються так, як ви очікували. Я зафіксував свій приклад.
— Ленґдон

4

Спробуйте скористатися цим запитом:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC

Не потрібно справи. IS NULL повертає 1, коли вираз NULL. Дивіться відповідь реверберації.
— contactmatt

3

Ви можете об'єднати свої NULL в ORDER BYзаяві:

select * from tablename
where <conditions>
order by
    coalesce(position, 0) ASC, 
    id DESC

Якщо ви хочете сортувати NULLs у ​​нижній частині, спробуйте coalesce(position, 100000). (Зробіть друге число більшим, ніж усі інші positionв дб.)


3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC

6
Чому ОП повинна спробувати це ? Хороші відповіді завжди матимуть пояснення того, що було зроблено і чому це було зроблено саме так, не тільки для ОП, але і для майбутніх відвідувачів ТА, які можуть знайти це запитання та прочитати вашу відповідь.
— RiggsFolly

2

Для DATEстовпця можна використовувати:


NULLS останні:

ORDER BY IFNULL(`myDate`, '9999-12-31') ASC

Останні заготовки:

ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC

1

Для досягнення наступного результату:

1, 2, 3, 4, NULL, NULL, NULL.

Використовуйте синтаксис USE, поставте -(minus sign)перед назвою поля та використовуйте зворотний_поряд_типу (наприклад: Якщо ви хочете замовити наказ ASC, тоді використовуйте DESC або якщо ви хочете замовити DESC, тоді використовуйте ASC)

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC


1

Це добре працює:

SELECT * FROM tablename ORDER BY position = 0, position ASC;

position
1 
2
3
0
0

-8

Чому ви не замовляєте НУЛЬСЬКИЙ ОСТАНИЙ?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 

NULLS LAST- яка версія MySQL була представлена?
— crmpicco

2
@Panique, ти маєш на увазі (MS) SQL Server?
— d -_- b

1
ця відповідь не стосується MySQL
— PeppyHeppy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.