Сортировка списка сотрудников по дням недели, начиная с понедельника в Oracle - PullRequest
0 голосов
/ 29 января 2019

Я пишу общие SQL-запросы, используя схему Скотта по умолчанию в Oracle.Используя таблицу emp.

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

Я написал этот запрос следующим образом:

select * from emp order by to_char(hiredate,'DAY') ; 

Но приведенный выше запрос отображает результаты в алфавитном порядке.порядок дней недели, т. е. (люди, нанятые в пятницу, идут сверху, затем в понедельник, субботу и т. д.)

Kinldy help.

1 Ответ

0 голосов
/ 29 января 2019

Попробуйте:

select * from emp order by trunc(hire_date) - trunc(hire_date, 'IW')

Это работает путем вычисления количества дней, прошедших с начала недели (начиная с понедельника).Он вернет 0 для понедельника и 6 для воскресенья.


Почему это работает

trunc(hire_date) - trunc(hire_date, 'IW')

Это все в документации Спецификаторы формата даты Oracle :

IW: календарная неделя года (1-52 или 1-53), как определено стандартом ISO 8601. В понедельник начинается календарная неделя .

Поскольку этот спецификатор опирается на стандарт ISO, на него не влияют настройки NLS сеанса, в котором он вызывается (см. Подробнее оосложнений этого избежать).Это делает этот подход полностью переносимым (и все же довольно эффективным, поскольку он состоит всего из двух преобразований).


Проблема с TO_CHAR подходом

Oracle предоставляет функцию TO_CHAR() , которую можно использовать со спецификатором формата D для возврата дня недели.Как задокументировано, этот элемент зависит от территории NLS сеанса .

В NLS_TERRITORY документации написано:

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

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

Но учтите, что этот параметр также контролирует по умолчанию других параметров сеанса (формат даты, десятичный разделитель, символ валюты, ...): его изменение может повлиять на другие запросы, выполняющиеся в том жесессия удивительным образом.

Рассмотрим эту демонстрацию

Сегодня среда, 28 января, следовательно, третий день недели.Мы создаем новый сеанс без указания какого-либо параметра NLS, а затем:

SELECT parameter, value from v$nls_parameters WHERE parameter = 'NLS_TERRITORY';

PARAMETER     | VALUE  
:------------ | :------
NLS_TERRITORY | AMERICA
 SELECT TO_CHAR(sysdate, 'd') FROM DUAL;

 | TO_CHAR(SYSDATE,'D') |
 | :------------------- |
 | 4                    |

При использовании территории сервера по умолчанию (Америка) мы получаем неправильный результат: Oracle считает, что в Америкенедели начинаются в воскресенье.

Давайте изменим параметр на территорию, где недели начинаются в понедельник:

ALTER SESSION SET NLS_TERRITORY = 'FRANCE';
SELECT TO_CHAR(sysdate, 'd') FROM DUAL;

 | TO_CHAR(SYSDATE,'D') |
 | :------------------- |
 | 3                    |

Теперь мы получаем желаемый результат ... Однако вы должны знать, что втем временем Oracle изменил параметр сеанса NLS_NUMERIC_CHARACTERS с ., на ,: это произошло из-за того, что значение по умолчанию NLS_NUMERIC_CHARACTERS было неявно изменено (при изменении NLS_TERRITORY) И никакое значение не было явно для этого набора параметровклиентом.Tricky.

Демонстрация на скрипте БД

Примечание: в отличие от параметра NLS_DATE_LANGUAGE, Oracle не позволяет передавать NLS_TERRITORY в качестве третьегоаргумент TO_CHAR (я полагаю, что это потому, что он контролирует значения по умолчанию других параметров).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...