Сортировка по дням рождения
Такая сортировка может потребоваться, например, для установления очередности празднования дней рождения сотрудников. Особенность подобной сортировки заключается в том, что год не учитывается вовсе, а даты упорядочиваются сначала по месяцу, а потом по дню месяца.
Возьмём в качестве примера таблицу Battles, а именно, столбец date. Ясно, что сортировка просто по дате (date) не даст желаемого результата из-за года (так, например, 15-е ноября будет предшествовать 20-му октября):
select date
from Battles
order by date;
[[ 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;
[[ column ]] |
---|
[[ value ]] |
select date
from Battles
order by convert(CHAR(5),date,110);
[[ 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);
[[ column ]] |
---|
[[ value ]] |
Что касается производительности, то вы можете выбрать любой вариант, т.к. оптимизатор строит для них идентичные планы.
В заключение представим последний запрос в более наглядном виде, добавив в него еще и “виновника торжества”:
select DAY(date) BD_day, DATENAME(mm, date) BD_month, name
from Battles
order by MONTH(date), DAY(date);
[[ column ]] |
---|
[[ value ]] |
Функция CONVERT специфична для SQL Server, т.е. она с большой вероятностью отсутствует в других СУБД.
Чтобы решить нашу задачу сортировки дней рождения в других СУБД, будем следовать первому способу, т.е. использовать подходящую функцию, которая выполняет преобразование даты в текстовый формат “MM-DD” (месяц-день).
MySQL
В MySQL такой функцией является DATE_FORMAT:
SELECT date,DATE_FORMAT(date,'%m-%d') "m-d"
FROM Battles;
[[ column ]] |
---|
[[ value ]] |
Результат
date | m-d |
---|---|
1962-10-20 00:00:00 | 10-20 |
1962-10-25 00:00:00 | 10-25 |
1942-11-15 00:00:00 | 11-15 |
1941-05-25 00:00:00 | 05-25 |
1943-12-26 00:00:00 | 12-26 |
1944-10-25 00:00:00 | 10-25 |
Соответственно, запрос, выполняющий сортировку по “дням рождения”, будет выглядеть так:
SELECT date
FROM Battles
ORDER BY DATE_FORMAT(date,'%m-%d');
[[ column ]] |
---|
[[ value ]] |
PostgreSQL & Oracle
В PostgreSQL и Oracle имеется функция TO_CHAR, задающая формат текстового представления даты. Вот пример запроса (PostgreSQL), возвращающий результат, аналогичный представленному выше для MySQL.
SELECT date, TO_CHAR(date,'mm-dd') "m-d"
FROM Battle;
[[ column ]] |
---|
[[ value ]] |
Единственное отличие для Oracle заключается не в синтаксисе самой функции, а в том, что ключевое слово date придется заключать в двойные кавычки для указания, что это имя столбца, а не тип данных.
Вот так для Oracle выглядит пример с сортировкой по дням рождения:
SELECT "date"
FROM Battles
ORDER BY TO_CHAR("date",'mm-dd');
[[ 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 |