25

如果我写

select ename, to_char(hiredate,'fmDay') as "Day" order by "Day";

然后它根据 Day 对结果进行排序;从周五开始,然后是周一和上周三,就像按字符排序一样。

但我想按星期几排序;从周一到周日。

4

17 回答 17

13

你按你的顺序得到它,因为你是按字符串排序的(这不起作用,因为你没有从任何东西中选择)。

您可以按用于以数字形式创建星期几的格式模型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)
于 2012-12-01T18:50:01.990 回答
13
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

假设用户有一个名为 classes 的表,该表中用户有 class_id(主键)、类名、Day。

于 2017-03-18T08:55:11.137 回答
10

当您可以添加另一列对应天数的 1-7 列然后按此列排序时,为什么要复杂化...

于 2013-09-14T12:48:50.723 回答
10

看看其他格式的TO_CHAR. 而不是 'fmDay' 使用 'D' 它将为您提供从 1 到 7 的星期几。然后您可以轻松地对其进行排序。

以下是日期格式列表: http: //docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm

于 2012-12-01T18:47:11.173 回答
9

我刚刚遇到了同样的要求——按星期几排序查询结果,但不是从星期日开始。我在 Oracle 中使用以下查询从星期一开始。(修改它以在一周中的任何一天开始订购,例如,将“MONDAY”更改为“TUESDAY”。)

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'))
于 2016-09-18T21:59:47.700 回答
8

将星期几映射到值 1-7的D格式掩码。to_char

但!

其输出取决于客户端对 NLS_TERRITORY 的设置。美国认为星期日是第一天。而世界其他大部分地区认为星期一是开始:

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 
于 2019-05-13T12:49:58.730 回答
7

如果您希望星期一始终被视为一周的第一天,您可以使用:

-- 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<>小提琴演示

于 2019-05-10T19:48:36.127 回答
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')将“星期一”放入名为“星期日”的框中。

于 2018-09-06T10:58:41.900 回答
5

正如它所说,它有一个功能

SELECT *
FROM table
ORDER BY WEEKDAY(table.date);
于 2019-05-09T07:56:42.737 回答
2

发布答案可能会迟到,但从星期一开始按星期几排序似乎很简单。

select hiredate,dayname(hiredate) from emp order by (dayofweek(hiredate)+5)%7; 

回答为什么要加 5 ?

因为,在数字中,星期日的值为 1,星期一的值为 2……而星期六的值为 7

因此,从星期一开始,2 + 5 = 7 和 mod(%) 和 7 将为我们提供新值。

您可以更改此数字以从一周中的任何其他日期开始。

于 2021-06-12T10:31:52.317 回答
1

我通过给你一个从 1 而不是 0 开始的结果来改进 Ben 的答案。查询将是这样的:

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)

希望这可以帮助 :)

于 2019-05-13T06:47:12.520 回答
1

这应该在 sql 中解决问题:

ORDER BY 
     CASE DATENAME(dw,<<enter your date variable here>>)
          WHEN 'Monday' THEN 1
          WHEN 'Tuesday' THEN 2
          WHEN 'Wednesday' THEN 3
          WHEN 'Thursday' THEN 4 
          WHEN 'Friday' THEN 5 
          WHEN 'Saturday' THEN 6
          WHEN 'Sunday' Then 7
     END ASC;

当然,如果您想要不同的顺序,您只需在之后切换值。

于 2020-03-17T14:33:30.003 回答
1

至少对于 Postgres,要让星期一始终是第 1 天,请使用TO_CHAR(b, 'ID')返回 ISO 8601 一周中的一天 - 星期一 (1) 到星期日 (7)。

这是国际标准组织 (ISO) 的一周中的一天,因此在“ID”中的 D 前面是 I。

https://www.postgresqltutorial.com/postgresql-to_char/

于 2020-06-17T10:08:45.960 回答
1

我有一些简单的想法希望你喜欢。我不知道您使用的是哪个 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;

我你想在一周结束后下周开始,然后找到一个月的季度并按顺序添加。

仅用于查找 Quarter in(MSSQL):select DatePart(QUARTER, cast(cast(mydate as char(8)) as date))

于 2019-05-15T05:39:20.620 回答
1
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. 
于 2019-05-13T13:54:56.940 回答
0

我认为这为时已晚,但如果其他人需要,我会将其留在这里。

您可以按星期几订购,但这取决于您的会话区域。

为了显示领土,您可以简单地执行以下查询:

SELECT * FROM V$NLS_PARAMETERS WHERE parameter = 'NLS_TERRITORY';

NLS_TERRITORY指定区域的名称,该区域的日期和星期编号要遵循其约定。

回到前面的查询,如果你有AMERICAas 值,那么 Monday 的值为 2。

要从周一到周日订购您的结果,您至少有 2 条道路:

1- 减少一天hire_date

SELECT * FROM employees ORDER BY TO_CHAR(hire_date - 1, 'd');

2- 将区域更改为以 1 作为星期一值的值,例如FRANCE

ALTER SESSION SET NLS_TERRITORY = 'FRANCE';

SELECT * FROM employees ORDER BY TO_CHAR(hire_date, 'd');
于 2021-02-15T15:49:37.580 回答
0

这是我的解决方案。

select ename, to_char(hiredate,'fmDay') "Day"
from employees
order by DECODE(to_number(to_char(hiredate ,'D'))-1,
                                                0, 7,
                to_number(to_char(hiredate ,'D'))-1);

基本上使用 to_char 函数中的 'D' 格式将日期转换为数字。

to_number(to_char(hire_date ,'D')

但这会导致星期日为 1,星期一为 2,依此类推,所以我减去 1 使星期一为 1。

(to_number(to_char(hire_date ,'D') - 1

然后我使用 DECODE 函数基本上说如果 0,则 7,否则为原始数字。这只会使星期日变成 7 而不是 0,其他一切都在适当的位置(星期一是 1,星期二是 2……依此类推)。

DECODE(to_number(to_char(hire_date ,'D'))-1,
                                                0, 7,
                to_number(to_char(hire_date ,'D'))-1);
于 2022-02-11T01:40:13.973 回答