Сортировка по дням недели с понедельника по воскресенье

Если я пишу

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))