问题
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