MySQL / 6. Сортировка результатов запроса

Сортировка и значения NULL

Задача
Вы хотите упорядочить столбец, который может содержать значения NULL.

Решение
Расположение значений NULL в упорядоченном списке менялось с течением времени и зависит от используемой вами версии MySQL. Если значения NULL появляются не там, где хотелось бы, измените их местоположение принудительно.

Обсуждение
Если упорядоченный столбец содержит значения NULL, MySQL группирует их и помещает все вместе. Учитывая то, что в операциях сравнения (как видно из следующего запроса) значения NULL считаются не равными друг другу, такое поведение MySQL может показаться странным:

mysql> SELECT NULL = NULL;

+----------------+
| NULL = NULL |
+----------------+
| NULL              |
+----------------+

С другой стороны, значения NULL все же больше похожи друг на друга, чем на значения не-NULL, и, в любом случае, хорошего способа различать значения NULL пока не предложено. Итак, значения NULL группируются вместе и могут помещаться или в начало, или в конец отсортированного списка, в зависимости от используемой версии MySQL. До версии 4.0.2 значения NULL располагались в начале списка (или в конце, при сортировке по убыванию). Начиная с версии 4.0.2, MySQL упорядочивает значения NULL согласно спецификации ANSI SQL и всегда помещает их в начало списка, вне зависимости от направления сортировки.Если вы хотите поместить значения NULL в тот или другой конец упорядоченого вывода, то можете сделать это вне зависимости от того, с какой версией MySQL работаете. Пусть есть таблица t, имеющая такое содержимое:

mysql> SELECT val FROM t;

+-------+
| val     |
+-------+
| 3        |
| 100    |
| NULL  |
| NULL  |
| 9        |
+-------+

Обычно сортировка располагает значения NULL в начале списка:

mysql> SELECT val FROM t ORDER BY val;

+------+
| val    |
+------+
| NULL |
| NULL |
| 3       |
| 9       |
| 100   |
+------+

Чтобы вместо этого выводить их в конце списка, укажите в инструкции ORDER BY дополнительный столбец, который будет сопоставлять значениям NULL значение, превышающее значения не-NULL:

mysql> SELECT val FROM t ORDER BY IF(val IS NULL,1,0), val;

+------+
| val    |
+------+
| 3       |
| 9       |
| 100   |
| NULL |
| NULL |
+------+

То же самое возможно и для DESC:

mysql> SELECT val FROM t ORDER BY IF(val IS NULL,1,0), val DESC;

+------+
| val    |
+------+
| 100   |
| 9       |
| 3       |
| NULL |
| NULL |
+------+

Если оказывается, что MySQL помещает значения NULL в конец упорядоченного списка, а вам бы хотелось, чтобы они были в начале, используйте тот же прием, только поменяйте местами второй и третий аргументы функции IF(), чтобы сопоставлять значениям NULL значение меньшее, чем значения не-NULL:

IF(val IS NULL,0,1)

Статьи по MySQL на эту тему:

Размещение некоторых значений в начале или конце упорядоченного списка
Сортировка IP-адресов в числовом порядке
Сортировка в порядке, определенном пользователем
Сортировка значений ENUM
Сортировка и чувствительность к регистру