Сортировка по дням рождения

Такая сортировка может потребоваться, например, для установления очередности празднования дней рождения сотрудников. Особенность подобной сортировки заключается в том, что год не учитывается вовсе, а даты упорядочиваются сначала по месяцу, а потом по дню месяца.

Возьмём в качестве примера таблицу Battles, а именно, столбец date. Ясно, что сортировка просто по дате (date) не даст желаемого результата из-за года (так, например, 15-е ноября будет предшествовать 20-му октября):

select date
from Battles
order by date;
🚫
[[ error ]]
[[ column ]]
[[ value ]]
date
1941-05-25 00:00:00.000
1942-11-15 00:00:00.000
1943-12-26 00:00:00.000
1944-10-25 00:00:00.000
1962-10-20 00:00:00.000
1962-10-25 00:00:00.000

Для выполнения требуемой сортировки можно предложить два варианта (SQL Server).

1. Использование функции CONVERT

При этом способе мы преобразуем дату к текстовому представлению в формате “mm-dd”

select convert(CHAR(5), date, 110) "mm-dd"
from Battles;
🚫
[[ error ]]
[[ column ]]
[[ value ]]
по которому и выполним сортировку:

select date
from Battles
order by convert(CHAR(5),date,110);
🚫
[[ error ]]
[[ column ]]
[[ value ]]
date
1941-05-25 00:00:00.000
1962-10-20 00:00:00.000
1962-10-25 00:00:00.000
1944-10-25 00:00:00.000
1942-11-15 00:00:00.000
1943-12-26 00:00:00.000

2. Использование функций MONTH и DAY

Здесь мы используем встроенные функции, которые возвращают компоненты даты - месяц (MONTH) и день (DAY) соответственно. По этим компонентам выполним сортировку:

select date
from Battles
order by MONTH(date), DAY(date);
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Что касается производительности, то вы можете выбрать любой вариант, т.к. оптимизатор строит для них идентичные планы.

В заключение представим последний запрос в более наглядном виде, добавив в него еще и “виновника торжества”:

select DAY(date) BD_day, DATENAME(mm, date) BD_month, name
from Battles
order by MONTH(date), DAY(date);
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Функция CONVERT специфична для SQL Server, т.е. она с большой вероятностью отсутствует в других СУБД.

Чтобы решить нашу задачу сортировки дней рождения в других СУБД, будем следовать первому способу, т.е. использовать подходящую функцию, которая выполняет преобразование даты в текстовый формат “MM-DD” (месяц-день).

MySQL

В MySQL такой функцией является DATE_FORMAT:

SELECT date,DATE_FORMAT(date,'%m-%d') "m-d"
FROM Battles;
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Результат

datem-d
1962-10-20 00:00:0010-20
1962-10-25 00:00:0010-25
1942-11-15 00:00:0011-15
1941-05-25 00:00:0005-25
1943-12-26 00:00:0012-26
1944-10-25 00:00:0010-25

Соответственно, запрос, выполняющий сортировку по “дням рождения”, будет выглядеть так:

SELECT date
FROM Battles
ORDER BY DATE_FORMAT(date,'%m-%d');
🚫
[[ error ]]
[[ column ]]
[[ value ]]

PostgreSQL & Oracle

В PostgreSQL и Oracle имеется функция TO_CHAR, задающая формат текстового представления даты. Вот пример запроса (PostgreSQL), возвращающий результат, аналогичный представленному выше для MySQL.

SELECT date, TO_CHAR(date,'mm-dd') "m-d"
FROM Battle;
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Единственное отличие для Oracle заключается не в синтаксисе самой функции, а в том, что ключевое слово date придется заключать в двойные кавычки для указания, что это имя столбца, а не тип данных.

Вот так для Oracle выглядит пример с сортировкой по дням рождения:

SELECT "date"
FROM Battles
ORDER BY TO_CHAR("date",'mm-dd');
🚫
[[ error ]]
[[ column ]]
[[ value ]]
date
1941-05-25 00:00:00
1962-10-20 00:00:00
1962-10-25 00:00:00
1944-10-25 00:00:00
1942-11-15 00:00:00
1943-12-26 00:00:00