Reputation: 11
I am writing general sql queries using the default scott schema in oracle. Using the emp table.
Here I want to display and sort the results on the basis of day which should start from Monday. i.e those hired on Monday should come at the top , then for tuesday and so on till sunday.
I wrote this query as :
select * from emp order by to_char(hiredate,'DAY') ;
But the above query is displaying results in alphabetical order of the week days i.e ( People hired on Friday coming at the top , then Monday , Saturday and so on)
Kinldy help.
Upvotes: 1
Views: 982
Reputation: 222402
Try :
select * from emp order by trunc(hire_date) - trunc(hire_date, 'IW')
This works by computing the number of days elapsed since the beginning of the week (starting Monday). It will return 0
for Monday and 6
for Sunday.
Why this works
trunc(hire_date) - trunc(hire_date, 'IW')
It's all in the documentation of Oracle date format specifiers :
IW
: Calendar week of year (1-52 or 1-53), as defined by the ISO 8601 standard. A calendar week starts on Monday.
As this specifier relies on ISO standard, it is not affected by the NLS settings of the session in which it is called (see further about the complications this avoids). This makes this approach full portable (and still quite efficient, as it consists in just two conversions).
The problem with the TO_CHAR
approach
Oracle provides the TO_CHAR()
function which can be used with the D
format specifier to return the day of the week. As documented, this element depends on the NLS territory of the session.
The NLS_TERRITORY
documentation says :
NLS_TERRITORY
specifies the name of the territory whose conventions are to be followed for day and week numbering.
By default, this session parameter is initialized from server's default. So to use the D
specifier in a portable way, you would need to first alter your session settings.
But beware that this parameter also controls the default of other session parameters (date format, decimal separator, currency symbol, ...) : modifying it could affect other queries running in the same session in suprising ways.
Consider this demonstration
Today is Wednesday, January 28, hence the third day of the week. We are creating a new session without specifying any NLS parameter, and then :
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 |
When using server's default territory (America), we are getting the wrong result : Oracle considers that, in America, weeks start on Sunday.
Let's alter the parameter to a territory where weeks start on Monday :
ALTER SESSION SET NLS_TERRITORY = 'FRANCE';
SELECT TO_CHAR(sysdate, 'd') FROM DUAL;
| TO_CHAR(SYSDATE,'D') |
| :------------------- |
| 3 |
Now we are getting the result we wanted... However, you should aware that, in the meantime, Oracle changed session parameter NLS_NUMERIC_CHARACTERS
from .,
to ,
: this happened because the default value of NLS_NUMERIC_CHARACTERS
was implicitely changed (when NLS_TERRITORY
was changed) AND no value had been explicitely for this parameter set by the client. Tricky.
NB : unlike NLS_DATE_LANGUAGE
parameter, Oracle does not allow to pass NLS_TERRITORY
as a third argument to TO_CHAR
(I imagine that it's because it controls the defaults of other parameters).
Upvotes: 2