MySQL Orderby по числу, нуля последний


280

В настоящее время я делаю очень простой OrderBy в своем заявлении.

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

Проблема в том, что записи NULL для 'position' обрабатываются как 0. Поэтому все записи с позицией как NULL появляются раньше, чем с 1,2,3,4. например:

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

Есть ли способ добиться следующего заказа:

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

8
Вам следует пересмотреть ответ пользователя 1052545. Это проще, не требует знания максимальных значений и может быть быстрее (при условии, что вычисление выражения может быть быстрее, чем вызов функции).
— Стив Клей

Ответы:


568

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). Я думаю (мне лень проверять) это работает для всех числовых столбцов (timestamp, float ...).
— Мартин

6
@koral: это простое (и полезное) математическое выражение, которое переворачивает порядок, оно не будет удалено, если сам язык не изменится кардинально.
— Белл

11
Как следует из комментариев, это работает для числовых столбцов, столбцов даты и времени? Но как насчет varchar? Может ли это быть применено и к varchar? Я попытался применить его к полям varchar, но порядок, по-видимому, отличается от использования ASC или DESC.
— Sumit Desai

9
Не помешает ли это использованию возможного индекса для заказа по столбцу?
— Тарсис

306

Я нашел это, чтобы быть хорошим решением по большей части:

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

6
Без переопределения порядка работ: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
— Marçal Juan

5
Это лучшее решение.
— Рок Краль

4
Принятое решение не работает с TIMESTAMP в postgresql 9.3. Это решение делает ...
— Калу

2
Досадно, что MySQL не будет использовать индекс по полю, когда вы добавляете isnull (поле) к предложению order by (при использовании limit).
— Барри Келли

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
Это решение хрупкое и может привести к периодическим ошибкам
— Дмитрий Богданович


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

Если вы хотите, чтобы значения NULL сортировались снизу, попробуйте coalesce(position, 100000). (Сделайте второе число больше, чем все остальные positionв БД.)


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

6
Почему ОП должен попробовать это ? Хорошие ответы всегда будут содержать объяснение того, что было сделано и почему это было сделано не только для ОП, но и для будущих посетителей SO, которые могут найти этот вопрос и прочитать ваш ответ.
— 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.

ИСПОЛЬЗУЙТЕ синтаксис, -(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

Почему бы вам не заказать NULLS LAST?

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.