在Oracle中从星期一开始按星期几对员工列表进行排序

时间:2019-01-29 19:47:48

标签: oracle

我正在使用oracle中的默认scott模式编写常规sql查询。 使用emp表。

在这里,我想根据星期几开始显示和排序结果。也就是说,周一雇用的人员应该排在首位,然后是周二,以此类推,直到周日。

我将此查询写为:

select * from emp order by to_char(hiredate,'DAY') ; 

但是上面的查询以星期几的字母顺序显示结果,即(周五的受雇人员排在顶部,然后是周一,周六,依此类推)

Kinldy帮助。

1 个答案:

答案 0 :(得分:2)

尝试:

select * from emp order by trunc(hire_date) - trunc(hire_date, 'IW')

这可以通过计算自一周初(星期一开始)以来经过的天数来工作。它将在星期一返回0,在星期日返回6


为什么有效

trunc(hire_date) - trunc(hire_date, 'IW')

所有内容都在Oracle date format specifiers的文档中:

  

IW:一年中的日历周(1-52或1-53),由ISO 8601标准定义。 一个日历周从星期一开始

由于此说明符依赖于ISO标准,因此不受其调用所在会话的NLS设置的影响(有关避免的复杂性,请进一步参见)。这使该方法具有完全的可移植性(并且仍然有效,因为它只包含两次转换)。


TO_CHAR方法的问题

Oracle提供了TO_CHAR() function,可与D格式说明符一起使用以返回星期几。如记录所示,此元素取决于会话的NLS范围

NLS_TERRITORY documentation说:

  

NLS_TERRITORY指定要在日期和星期编号中遵循的惯例的地区名称。

默认情况下,此会话参数是从服务器的默认值初始化的。因此,要以可移植的方式使用D说明符,您首先需要更改会话设置。

但是请注意,此参数还会控制其他会话参数(日期格式,小数点分隔符,货币符号等)的 default :修改它可能会影响在同一会话中运行的其他查询令人惊讶的方式。

考虑此演示

今天是1月28日,星期三,因此是星期三。我们将在不指定任何NLS参数的情况下创建一个新会话,然后:

SELECT parameter, value from v$nls_parameters WHERE parameter = 'NLS_TERRITORY';

PARAMETER     | VALUE  
:------------ | :------
NLS_TERRITORY | AMERICA
 SELECT TO_CHAR(sysdate, 'd') FROM DUAL;

 | TO_CHAR(SYSDATE,'D') |
 | :------------------- |
 | 4                    |

在使用服务器的默认地区(美国)时,我们得到的结果是错误的:Oracle认为在美国,星期几从星期日开始。

让我们将参数更改为星期一从几周开始的地区:

ALTER SESSION SET NLS_TERRITORY = 'FRANCE';
SELECT TO_CHAR(sysdate, 'd') FROM DUAL;

 | TO_CHAR(SYSDATE,'D') |
 | :------------------- |
 | 3                    |

现在我们正在获得想要的结果...但是,您应该意识到,与此同时,Oracle将会话参数NLS_NUMERIC_CHARACTERS.,更改为,:这是因为NLS_NUMERIC_CHARACTERS的默认值被隐式更改(更改NLS_TERRITORY时),并且客户端没有为该参数集显式地设置任何值。棘手的。

Demo on DB Fiddle

NB:与NLS_DATE_LANGUAGE参数不同,Oracle不允许将NLS_TERRITORY作为第三个参数传递给TO_CHAR(我想这是因为它控制其他参数的默认值)。 / p>