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.