Week start from Sunday while calculating weekday - sql

I am trying to find the weekday for Sunday to Saturday. In oracle by default Monday is the first day of the week. So When I calculate weekday with following query
Select to_char(sysdate, 'D') from dual
as today is 09/12/2022 this is giving me result as 5 as week start from Monday. I want this should be calculated as week start from Sunday. Ideally, answer should be 6 if this week start from Sunday.
Is there any easy way to do it, I can use case statement, but that is not a good way. Please help.

Talk to your DBA to fix territory. If it was set to e.g. India, then you wouldn't have to calculate anything:
SQL> alter session set nls_territory = 'India';
Session altered.
SQL> Select to_char(sysdate, 'D') from dual;
T
-
6
SQL>

In Oracle, the first day of a week is determined by NLS_TERRITORY parameter. So use a value of NLS_TERRITORY where Sunday is the first weekday, for example, AMERICA.
alter session set nls_territory=RUSSIA
select to_char(sysdate, 'D')
from dual
TO_CHAR(SYSDATE,'D')
5
alter session set nls_territory=AMERICA
select to_char(sysdate, 'D')
from dual
TO_CHAR(SYSDATE,'D')
6
fiddle

Option 1: NLS_TERRITORY session parameter
In Oracle, the day of the week depends on the NLS_TERRITORY session setting:
SELECT TO_CHAR(DATE '2022-12-11', 'D') AS day, -- a sunday
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TERRITORY')
AS territory
FROM DUAL;
Outputs different values for different parameters. I.e., if you use:
ALTER SESSION SET NLS_TERRITORY='America';
ALTER SESSION SET NLS_TERRITORY='Germany';
ALTER SESSION SET NLS_TERRITORY='India';
ALTER SESSION SET NLS_TERRITORY='Oman';
ALTER SESSION SET NLS_TERRITORY='Bangladesh';
and run the query for each then the outputs are:
DAY
TERRITORY
1
AMERICA
7
GERMANY
1
INDIA
2
OMAN
3
BANGLADESH
So you could just pick the correct territory for your database, i.e.:
ALTER SESSION SET NLS_TERRITORY='India';
Option 2: Compare to the start of the ISO-week
Or if you want to be independent of the session settings then you can compare it to the start of the ISO-week (which is always midnight Monday) and offset by one day to change the comparison from Monday-Sunday to Sunday-Saturday:
SELECT TRUNC(SYSDATE + 1) - TRUNC(SYSDATE + 1, 'IW') + 1 AS day
FROM DUAL;
Which, for today (Friday) outputs:
DAY
6
fiddle

I found the answer to this, which is dead easy
select mod(to_char(sysdate,'D'),7)+1 as Weekday from Dual

Related

Trying to convert datetime in date in oracle

Hi i'm trying to convert date 01-03-2020 10:48:27 which obtained from query
SELECT
LAST_DAY( ADD_MONTHS(SYSDATE,-3 ) )+1
FROM
dual;
into '01-Mar-2020' but not able to do trying many concept
eg.
trunc(SELECT LAST_DAY( ADD_MONTHS(SYSDATE , - 3 ) )+1 FROM dual),'YEAR')
and
SELECT TRUNC(TO_DATE('SELECT LAST_DAY( ADD_MONTHS(SYSDATE , - 3 ) )+1 FROM dual','DD-MON-YY'), 'YEAR') "New Year" FROM DUAL;
but getting error
Any idea would be appreciated
You're making things way too complicated. Oracle TRUNC takes an additional parameter to specify whatever time interval to truncate to:
SELECT TRUNC(some_date_here, 'MON') FROM dual
If you put some_date_here as sysdate, then currently it will return 01-May-2020 until next month when it starts returning 01-Jun-2020
You can truncate to any interval; TRUNC 01/01/2000 12:34:56 with 'MI' will return 01/01/2000 12:34:00. Truncating to DD is the default (cut the time off). Truncating to DAY sets the date back to the day that started the week in the country oracle thinks it is in (probably a Sunday or Monday)
More info: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084
As I understood your problem you want to go from the current date, to the first of the month that was between 2 and < 3 months ago (so if it's May now, you want to go back to first of March until it's June, when you want to go back to first of April)
If you hence, in the current date of 5th May, want to go back to a date of 1 March, take 2 months off the current date and then TRUNC to the start of the month:
SELECT TRUNC(ADD_MONTHS(sysdate, -2), 'MON') FROM dual
Don't forget you can TRUNC to the nearest quarter of a year, so if you're doing a report that is "the current quarter", then looking at a variation of TRUNC(sysdate, 'Q') would be the way to go
Lastly, I'd urge you NOT to use oracle to convert your dates to strings (in most cases) - if you keep it as a date all the way 'tIl it hits the user's computer it can be formatted for their regional preferences. If you make a decision as to the format as its coming out the dB it makes it much harder to deliver a good international experience for your app
"Convert" in your case means TO_CHAR; alter session is here to set default format for this session.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select
2 last_Day(add_months(sysdate, -3)) + 1 orig,
3 to_char(last_day(add_months(sysdate, -3)) + 1, 'dd-Mon-yyyy', 'nls_Date_language = english') result
4 from dual;
ORIG RESULT
------------------- --------------------
01.03.2020 07:25:44 01-Mar-2020
SQL>
Or, if you altered the session, you'd get it as
SQL> alter session set nls_date_language = 'english';
Session altered.
SQL> alter session set nls_date_format = 'dd-Mon-yyyy';
Session altered.
SQL> select
2 last_Day(add_months(sysdate, -3)) + 1 orig
3 from dual;
ORIG
-----------
01-Mar-2020
SQL>
But, yes - usually we TO_CHAR it.

How to change the week start day as sunday for database in oracle for reporting purpose

Have tried changing NLS_TERRITORY and NLS_LANGUAGE still database is showing Monday as starting week.
Alter session set nls_territory = 'America'
select TRUNC(sysdate, 'iw') AS iso_week_start_date,
TRUNC(sysdate, 'iw') + 7 - 1/86400 AS iso_week_end_date
from dual;
2 3
ISO_WEEK ISO_WEEK
--------- ---------
20-AUG-18 26-AUG-18
Here the ISO_WEEK_START_DATE should start from 19-AUG-2018 which is sunday
TRUNC(sysdate, 'iw') returns first day of week according to ISO-8601 which is always Monday. For local weeks use TRUNC(sysdate, 'WW') which depends on current user session NLS_TERRITORY

DB2 to Oracle Conversion For Basic Date Time Column Between Clause

What this is doing is selecting all columns from TABLE where a specific date time column is between last Sunday and this coming Saturday, 7 days total (no matter what day of the week you are running the query on)
I would like to have help converting the below statement into Oracle since I found out that it will not work on Oracle.
SELECT *
FROM TABLE
WHERE DATE_TIME_COLUMN
BETWEEN
current date - ((dayofweek(current date))-1) DAYS
AND
current date + (7-(dayofweek(current date))) DAYS
After poking around a bit more I was able to find something that worked for my specific problem with no administrator restrictions for whatever reason:
SELECT *
FROM TABLE
WHERE DATE_TIME_COLUMN
BETWEEN
TIMESTAMPADD(SQL_TSI_DAY, DayOfWeek(Current_Date)*(-1) + 1, Current_Date)
AND
TIMESTAMPADD(SQL_TSI_DAY, 7 - DayOfWeek(Current_Date), Current_Date)
Use TRUNC() to truncate to the start of the week:
SELECT *
FROM TABLE
WHERE DATE_TIME_COLUMN
BETWEEN trunc(sysdate, 'WW')
and
trunc(sysdate + 7, 'WW');
sysdate is the current system date, trunc truncates a data, and WW tells it to truncate to the week (rather than day, year, etc.).
Assuming DATE_TIME_COLUMN is - as it should be - of datatype date, I think this gets what you want.
where DATE_TIME_COLUMN between
next_day(sysdate,'SUNDAY')-7 and next_day(sysdate,'SATURDAY')
You may need to tweak it a bit. Please follow up studying the official docs on the NEXT_DAY function in the relevant docs at http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions106.htm#SQLRF00672
The proposed TRUNC does not guarantee you get the date of a particular day of the week:
SQL> alter session set nls_date_format='day dd-mon-yyyy';
Session altered.
SQL> select trunc(sysdate,'WW') from dual;
TRUNC(SYSDATE,'WW')
---------------------
friday 22-jan-2016
SQL> select trunc(sysdate+7,'WW') from dual;
TRUNC(SYSDATE+7,'WW')
---------------------
friday 29-jan-2016

Oracle SQL What does start_date-1 mean?

Oracle SQL What does start_date-1 mean?
Is it just one day less the start_date?
Assuming your datatype is a date or timestamp, yes, it will remove a full day from your date:
SELECT SYSDATE AS "start_date",
SYSDATE - 1 AS "start_date -1"
FROM DUAL;
Returns
26/08/2015 11:09:21 | 25/08/2015 11:09:21
YES. It will subrtract 1 day from the start_date.
Given that the data type of start_date is DATE or TIMESTAMP, subtracting N from it would subtract N number of days.
For example,
SQL> alter session set nls_date_format='DD-MM-YYYY HH24:MI:SS';
Session altered.
SQL> SELECT sysdate, sysdate -1 FROM DUAL;
SYSDATE SYSDATE-1
------------------- -------------------
26-08-2015 14:45:35 25-08-2015 14:45:35
SQL>
Remember, date has both date and time elements, so you will go back to previous day with exactly that time portion.
Yes it is 1 day earlier to start_date.

In oracle SQL, how would you obtain the timestamp representing the start of the week?

I'm using an Oracle 9i database and want to obtain, within a function, the timestamp representing the start of the week, i.e. The most recent monday, at 00:00:00.
I am aware that the timestamp representing the start of the current day is TO_TIMESTAMP(SYSDATE).
You can use the function next_day to get that:
SQL> select next_day(sysdate-7, 'MONDAY') FROM DUAL;
NEXT_DAY
---------
29-APR-13
Getting the start of the week should work with trunc (see docs).
So,
select to_timestamp(trunc(sysdate, 'D')) from dual
should work.
However, depending on your NLS settings, the first day of the week for oracle may well be Sunday.
this appears to return Monday before the day of week in question at midnight. to prove out just play around with sysdate and subtract days...
select case when to_Char(sysdate,'d') = 1 then
trunc(sysdate-6)
else
trunc(sysdate - (to_Char(sysdate,'d')-2))
END
from dual;
You can truncate a date to Monday with:
select trunc(sysdate, 'IW') FROM DUAL;