Сортировка по дням недели с понедельника по воскресенье
Если я пишу
select ename, to_char(hiredate,'fmDay') as "Day" order by "Day";
Затем он сортирует результат, основанный на Day like; с пятницы, затем в понедельник и в прошлую среду,
сортировка по символам.
Но я хочу сортировать его по дням недели; с понедельника по воскресенье.
Ответы
Ответ 1
Вы получаете это в том порядке, в каком вы находитесь, потому что вы упорядочиваете по строке (и это не сработает, потому что вы ничего не выбираете).
Вы можете упорядочить по модели формата, использованной для создания дня недели в числовой форме, D
, но, поскольку воскресенье равно 1, я бы порекомендовал использовать mod()
для этой работы.
т.е. принимая таблицу
create table a ( b date );
insert into a
select sysdate - level
from dual
connect by level <= 7;
Это будет работать:
select mod(to_char(b, 'D') + 5, 7) as dd, to_char(b, 'DAY')
from a
order by mod(to_char(b, 'D') + 5, 7)
Вот SQL Fiddle для демонстрации.
В вашем случае ваш запрос станет:
select ename, to_char(hiredate,'fmDay') as "Day"
from my_table
order by mod(to_char(hiredate, 'D') + 5, 7)
Ответ 2
Посмотрите на другие форматы для TO_CHAR
. Вместо "fmDay" используйте "D", и он даст вам день недели с 1 по 7. Тогда вы можете легко отсортировать по нему.
Вот список форматов даты: http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm
Ответ 3
Зачем усложнять, когда вы можете добавить еще один столбец с цифрами 1-7, соответствующий дням, а затем отсортировать по этому столбцу...
Ответ 4
Я просто столкнулся с тем же требованием - упорядочить результат запроса по дням недели, но не начинать с воскресенья. Я использовал следующий запрос в Oracle, чтобы начать с понедельника. (Измените его, чтобы начать заказ с любого дня недели, например, измените "MONDAY" на "ВТОРНИК".)
SELECT ename, to_char(hiredate, 'fmDAY') AS "Day"
FROM emp
ORDER BY (next_day(hiredate, 'MONDAY') - hiredate) DESC
Или:
SELECT ename, to_char(hiredate, 'fmDAY') AS "Day"
FROM emp
ORDER BY (hiredate - next_day(hiredate, 'MONDAY'))
Ответ 5
SELECT
*
FROM
classes
ORDER BY
CASE
WHEN Day = 'Sunday' THEN 1
WHEN Day = 'Monday' THEN 2
WHEN Day = 'Tuesday' THEN 3
WHEN Day = 'Wednesday' THEN 4
WHEN Day = 'Thursday' THEN 5
WHEN Day = 'Friday' THEN 6
WHEN Day = 'Saturday' THEN 7
END ASC
Предполагая, что у пользователя есть таблица с именами классов в этой таблице, у пользователя есть class_id (первичный ключ), имя класса, Day.
Ответ 6
Это просто.
SELECT last_name, hire_date,TO_CHAR(hire_date, 'DAY') DAY
FROM employees
ORDER BY TO_CHAR(hire_date - 1, 'd');
TO_CHAR(hire_date - 1, 'd')
помещает "понедельник" в поле с именем "воскресенье".
Ответ 7
Как сказано, есть функция для этого:
SELECT *
FROM table
ORDER BY WEEKDAY(table.date);
Ответ 8
Если вы хотите, чтобы понедельник всегда рассматривался как первый день недели, вы можете использовать:
-- Not affected by NLS_TERRITORY
-- ALTER SESSION SET NLS_TERRITORY="AMERICA"; -- Sunday is first day of week
-- ALTER SESSION SET NLS_TERRITORY="GERMANY"; -- Monday is first day of week
SELECT *
FROM tab
ORDER BY 1+TRUNC(dt)-TRUNC(dt,'IW');
ДБ <> Fiddle Demo
Ответ 9
Маска формата D
для to_char
отображает дни недели в значения 1-7.
Но!
Вывод этого зависит от настройки клиента для NLS_TERRITORY. США считают воскресенье днем 1. Принимая во внимание, что большинство остального мира считают понедельник началом:
alter session set nls_territory = AMERICA;
with dts as (
select date'2018-01-01' + level - 1 dt
from dual
connect by level <= 7
)
select to_char ( dt, 'Day' ) day_name,
to_char ( dt, 'd' ) day_number
from dts
order by day_number;
DAY_NAME DAY_NUMBER
Sunday 1
Monday 2
Tuesday 3
Wednesday 4
Thursday 5
Friday 6
Saturday 7
alter session set nls_territory = "UNITED KINGDOM";
with dts as (
select date'2018-01-01' + level - 1 dt
from dual
connect by level <= 7
)
select to_char ( dt, 'Day' ) day_name,
to_char ( dt, 'd' ) day_number
from dts
order by day_number;
DAY_NAME DAY_NUMBER
Monday 1
Tuesday 2
Wednesday 3
Thursday 4
Friday 5
Saturday 6
Sunday 7
К сожалению, в отличие от многих других параметров NLS, вы не можете передать NLS_TERRITORY в качестве третьего параметра to_char
:
with dts as (
select date'2018-01-01' dt
from dual
)
select to_char ( dt, 'Day', 'NLS_DATE_LANGUAGE = SPANISH' ) day_name
from dts;
DAY_NAME
Lunes
with dts as (
select date'2018-01-01' dt
from dual
)
select to_char ( dt, 'Day', 'NLS_TERRITORY = AMERICA' ) day_name
from dts;
ORA-12702: invalid NLS parameter string used in SQL function
Поэтому любое решение, полагающееся на D
для сортировки, является ошибкой!
Чтобы избежать этого, вычтите самый последний понедельник из даты (если сегодня понедельник, самый последний понедельник = сегодня). Вы можете сделать это с помощью маски формата IW
. Что возвращает начало недели ISO. Который всегда понедельник:
with dts as (
select date'2018-01-01' + level - 1 dt
from dual
connect by level <= 7
)
select to_char ( dt, 'Day' ) day_name,
( dt - trunc ( dt, 'iw' ) ) day_number
from dts
order by day_number;
DAY_NAME DAY_NUMBER
Monday 0
Tuesday 1
Wednesday 2
Thursday 3
Friday 4
Saturday 5
Sunday 6
Для сортировки с воскресенья по субботу добавьте одну к дате, прежде чем найти начало недели ISO:
with dts as (
select date'2018-01-01' + level - 1 dt
from dual
connect by level <= 7
)
select to_char ( dt, 'Day' ) day_name,
( dt - trunc ( dt + 1, 'iw' ) ) day_number
from dts
order by day_number;
DAY_NAME DAY_NUMBER
Sunday -1
Monday 0
Tuesday 1
Wednesday 2
Thursday 3
Friday 4
Saturday 5
Ответ 10
Я улучшил ответ Бена, дав вам результат, который начинается с 1, а не с 0. Запрос будет выглядеть так:
select
mod(to_char(b, 'D')+ 5, 7) +1 as dd,
to_char(b, 'DAY')
from a
order by mod(to_char(b, 'D')+ 5, 7);
С другой стороны, если вы хотите, чтобы ваша неделя начиналась с воскресенья, используйте этот запрос:
select
mod(to_char(b, 'D')+ 6, 7) +1 as dd,
to_char(b, 'DAY')
from a
order by mod(to_char(b, 'D')+ 6, 7)
Надеюсь это поможет :)
Ответ 11
with s as (select trunc(sysdate) + level dt from dual connect by level <= 7)
select to_char(dt, 'fmDay', 'nls_date_language=English') d
from s
order by dt - trunc(dt, 'iw');
D
------------------------------------
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
7 rows selected.
Ответ 12
У меня есть простая идея, надеюсь, вам понравится. Я не знаю, какой sql вы используете, поэтому, пожалуйста, исправьте синтаксическую ошибку.
select ename, to_char(hiredate,'fmDay') as "Day" from ABC_TABLE
JOIN (VALUES (1,'Monday'),(2,'Tuesday'),(3,'Wednesday'),(4,'Thursday'),(5,'Friday'),(6,'Saturday'),(7,'Sunday')) weekdays(seq,[Days]) on
ABC_TABLE.to_char(hiredate,'fmDay') = weekdays.[Days]
order by weekdays.seq;
Если вы хотите начать на следующей неделе после конца недели, то просто найдите четверть месяца и добавьте в порядок по clouse.
только для поиска четверти в (MSSQL): select DatePart(QUARTER, cast(cast(mydate as char(8)) as date))