问题
If I write
select ename, to_char(hiredate,'fmDay') as "Day" order by "Day";
Then it sorts the result based on Day like; from Friday, then Monday and last Wednesday, like sorting by characters.
But I want to sort it by day of the week; from Monday to Sunday.
回答1:
You're getting it in the order you are because you're ordering by a string (and this wouldn't work because you're not selecting from anything).
You could order by the format model used to create the day of the week in numeric form, D, but as Sunday is 1 in this I would recommend using mod() to make this work.
i.e. assuming the table
create table a ( b date );
insert into a
select sysdate - level
from dual
connect by level <= 7;
This would work:
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)
Here's a SQL Fiddle to demonstrate.
In your case your query would become:
select ename, to_char(hiredate,'fmDay') as "Day"
from my_table
order by mod(to_char(hiredate, 'D') + 5, 7)
回答2:
Take a look at other formats for TO_CHAR. Instead of 'fmDay' use 'D' and it will give you the day of the week from 1 to 7. Then you can easily sort on it.
Here's a list of date formats: http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm
回答3:
I just encountered the same requirement -- to order a query result by day of the week, but not starting with Sunday. I used the following query in Oracle to start w/ Monday. (Modify it to start the ordering w/ any day of the week, e.g., change 'MONDAY' to 'TUESDAY'.)
SELECT ename, to_char(hiredate, 'fmDAY') AS "Day"
FROM emp
ORDER BY (next_day(hiredate, 'MONDAY') - hiredate) DESC
Or:
SELECT ename, to_char(hiredate, 'fmDAY') AS "Day"
FROM emp
ORDER BY (hiredate - next_day(hiredate, 'MONDAY'))
回答4:
The D format mask of to_char maps days of the week to the values 1-7.
But!
The output of this depends on the client's setting for NLS_TERRITORY. The US considers Sunday to be day 1. Whereas most of the rest of the world consider Monday to be the start:
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
Sadly, unlike many other NLS parameters, you can't pass NLS_TERRITORY as the third parameter of 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
So any solution relying on D for sorting is a bug!
To avoid this, subtract the most recent Monday from the date (if today is Monday, the most recent Monday = today). You can do this with the IW format mask. Which returns the start of the ISO week. Which is always a Monday:
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
For Sunday-Saturday sorting, add one to the date before finding the start of the ISO week:
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
回答5:
Why to complicate when you can add another column with numbers 1-7 corresponding to days and then sort by this column...
回答6:
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
Assuming that user has a table called classes in that table user has class_id (primary key), class name, Day.
回答7:
If you want Monday to be always treated as first day of week you could use:
-- 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');
db<>fiddle demo
回答8:
It's simple.
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') puts a 'Monday' into a box named 'Sunday'.
回答9:
As it's said, there's a function for it:
SELECT *
FROM table
ORDER BY WEEKDAY(table.date);
回答10:
I improved on Ben's answer by giving you a result which starts from 1 rather than 0. The query would be like this:
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);
On the other hand, if you want your week to start from Sunday, then you should use this query:
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)
Hope this helps :)
回答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:
I have some simple idea hope you like it. i don't which sql you are using so please correct syntax error.
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;
I you want to start next week after end a week then just find quarter of month and add in order by clouse.
just for in of find Quarter in(MSSQL): select DatePart(QUARTER, cast(cast(mydate as char(8)) as date))
来源:https://stackoverflow.com/questions/13662451/sort-by-day-of-the-week-from-monday-to-sunday