2012
January
2/1/2012
9/1/2012
16/1/2012
23/1/2012
30/1/2012
February
6/2/2012
.
.
.
.
and so on till decemeber.
the dates mentioned are mondays..How do i get the output in this format?? please help
One option
SQL> ed
Wrote file afiedt.buf
1 select next_day(trunc(sysdate,'YYYY') + 7*(level-1), 'MON' )
2 from dual
3* connect by level <= 53
SQL> /
NEXT_DAY(
---------
02-JAN-12
09-JAN-12
16-JAN-12
23-JAN-12
30-JAN-12
06-FEB-12
13-FEB-12
20-FEB-12
27-FEB-12
05-MAR-12
12-MAR-12
<<snip>>
03-DEC-12
10-DEC-12
17-DEC-12
24-DEC-12
31-DEC-12
53 rows selected.
Query:
select distinct next_day(to_date('01-01-2012','mm-dd-yyyy')-1+level,'Monday') All_MON from dual
connect by level <= floor(to_date('12-31-2011','mm-dd-yyyy') - to_date('01-01-2011','mm-dd-yyyy'))
order by All_MON;
Output:
01/02/2012 MONDAY
01/09/2012 MONDAY
01/16/2012 MONDAY
01/23/2012 MONDAY
01/30/2012 MONDAY
02/06/2012 MONDAY
02/13/2012 MONDAY
02/20/2012 MONDAY
02/27/2012 MONDAY
03/05/2012 MONDAY
03/12/2012 MONDAY
03/19/2012 MONDAY
03/26/2012 MONDAY
04/02/2012 MONDAY
04/09/2012 MONDAY
04/16/2012 MONDAY
04/23/2012 MONDAY
04/30/2012 MONDAY
05/07/2012 MONDAY
05/14/2012 MONDAY
05/21/2012 MONDAY
05/28/2012 MONDAY
06/04/2012 MONDAY
06/11/2012 MONDAY
06/18/2012 MONDAY
06/25/2012 MONDAY
07/02/2012 MONDAY
07/09/2012 MONDAY
07/16/2012 MONDAY
07/23/2012 MONDAY
07/30/2012 MONDAY
08/06/2012 MONDAY
08/13/2012 MONDAY
08/20/2012 MONDAY
08/27/2012 MONDAY
09/03/2012 MONDAY
09/10/2012 MONDAY
09/17/2012 MONDAY
09/24/2012 MONDAY
10/01/2012 MONDAY
10/08/2012 MONDAY
10/15/2012 MONDAY
10/22/2012 MONDAY
10/29/2012 MONDAY
11/05/2012 MONDAY
11/12/2012 MONDAY
11/19/2012 MONDAY
11/26/2012 MONDAY
12/03/2012 MONDAY
12/10/2012 MONDAY
12/17/2012 MONDAY
12/24/2012 MONDAY
12/31/2012 MONDAY
Related
I have 2 tables.
1st of them consists of working days for each month (year = 2020):
Month
Date from
Date to
January
01/01/2020
31/01/2020
February
01/02/2020
29/02/2020
March
01/03/2020
31/03/2020
2nd of them has a dates with public holidays for 2020 with the following format:
Date
Week day
Code
Working hours
01/01/2020
Wednesday
Holiday
0
08/03/2020
Sunday
Holiday
0
01/09/2020
Tuesday
Holiday
0
24/12/2020
Thursday
Holiday
0
I would like to create 1 table (with the format of 2nd table) which has data only working days excluding public holidays from 2nd table and weekends from calendar for 2020.
Thank you in advance for your help.
Regards,
You can create the table using:
CREATE TABLE working_days (
day DATE PRIMARY KEY,
week_day VARCHAR2(9)
GENERATED ALWAYS AS (CAST(RTRIM(TO_CHAR(day, 'FMDay')) AS VARCHAR2(9))),
code VARCHAR2(20),
working_hours NUMBER(4,2)
);
Then insert data using:
INSERT INTO working_days (day, code, working_hours)
WITH days (dt, date_to) AS (
SELECT TRUNC(date_from),
date_to
FROM working_day_ranges
UNION ALL
SELECT dt + INTERVAL '1' DAY,
date_to
FROM days
WHERE dt + INTERVAL '1' DAY <= date_to
)
SELECT dt, 'Working Day', 23
FROM days d
WHERE NOT EXISTS ( -- Not a holiday
SELECT 1
FROM holidays h
WHERE d.dt = h.dt
)
AND dt - TRUNC(dt, 'IW') < 5 -- Not a Saturday or Sunday;
ORDER BY dt;
(Alter the expected working hours, etc. as suits you.)
Which, assuming your tables:
CREATE TABLE working_day_ranges (Date_from, Date_to) AS
SELECT DATE '2020-01-01', DATE '2020-01-31' FROM DUAL UNION ALL
SELECT DATE '2020-02-01', DATE '2020-02-29' FROM DUAL UNION ALL
SELECT DATE '2020-03-01', DATE '2020-03-31' FROM DUAL;
ALTER TABLE working_day_ranges
ADD month VARCHAR2(8)
GENERATED ALWAYS AS (CAST(RTRIM(TO_CHAR(date_from, 'FMMonth')) AS VARCHAR2(8)));
CREATE TABLE holidays (dt, Code, Working_hours) AS
SELECT DATE '2020-01-01', 'Holiday', 0 FROM DUAL UNION ALL
SELECT DATE '2020-03-08', 'Holiday', 0 FROM DUAL UNION ALL
SELECT DATE '2020-09-01', 'Holiday', 0 FROM DUAL UNION ALL
SELECT DATE '2020-12-24', 'Holiday', 0 FROM DUAL;
ALTER TABLE holidays
ADD week_day VARCHAR2(9)
GENERATED ALWAYS AS (CAST(RTRIM(TO_CHAR(dt, 'FMDay')) AS VARCHAR2(9)));
Then:
SELECT * FROM working_days;
Outputs:
DAY
WEEK_DAY
CODE
WORKING_HOURS
02-JAN-20
Thursday
Working Day
23
03-JAN-20
Friday
Working Day
23
06-JAN-20
Monday
Working Day
23
07-JAN-20
Tuesday
Working Day
23
08-JAN-20
Wednesday
Working Day
23
09-JAN-20
Thursday
Working Day
23
10-JAN-20
Friday
Working Day
23
13-JAN-20
Monday
Working Day
23
14-JAN-20
Tuesday
Working Day
23
15-JAN-20
Wednesday
Working Day
23
16-JAN-20
Thursday
Working Day
23
17-JAN-20
Friday
Working Day
23
20-JAN-20
Monday
Working Day
23
21-JAN-20
Tuesday
Working Day
23
22-JAN-20
Wednesday
Working Day
23
23-JAN-20
Thursday
Working Day
23
24-JAN-20
Friday
Working Day
23
27-JAN-20
Monday
Working Day
23
28-JAN-20
Tuesday
Working Day
23
29-JAN-20
Wednesday
Working Day
23
30-JAN-20
Thursday
Working Day
23
31-JAN-20
Friday
Working Day
23
03-FEB-20
Monday
Working Day
23
04-FEB-20
Tuesday
Working Day
23
05-FEB-20
Wednesday
Working Day
23
06-FEB-20
Thursday
Working Day
23
07-FEB-20
Friday
Working Day
23
10-FEB-20
Monday
Working Day
23
11-FEB-20
Tuesday
Working Day
23
12-FEB-20
Wednesday
Working Day
23
13-FEB-20
Thursday
Working Day
23
14-FEB-20
Friday
Working Day
23
17-FEB-20
Monday
Working Day
23
18-FEB-20
Tuesday
Working Day
23
19-FEB-20
Wednesday
Working Day
23
20-FEB-20
Thursday
Working Day
23
21-FEB-20
Friday
Working Day
23
24-FEB-20
Monday
Working Day
23
25-FEB-20
Tuesday
Working Day
23
26-FEB-20
Wednesday
Working Day
23
27-FEB-20
Thursday
Working Day
23
28-FEB-20
Friday
Working Day
23
02-MAR-20
Monday
Working Day
23
03-MAR-20
Tuesday
Working Day
23
04-MAR-20
Wednesday
Working Day
23
05-MAR-20
Thursday
Working Day
23
06-MAR-20
Friday
Working Day
23
09-MAR-20
Monday
Working Day
23
10-MAR-20
Tuesday
Working Day
23
11-MAR-20
Wednesday
Working Day
23
12-MAR-20
Thursday
Working Day
23
13-MAR-20
Friday
Working Day
23
16-MAR-20
Monday
Working Day
23
17-MAR-20
Tuesday
Working Day
23
18-MAR-20
Wednesday
Working Day
23
19-MAR-20
Thursday
Working Day
23
20-MAR-20
Friday
Working Day
23
23-MAR-20
Monday
Working Day
23
24-MAR-20
Tuesday
Working Day
23
25-MAR-20
Wednesday
Working Day
23
26-MAR-20
Thursday
Working Day
23
27-MAR-20
Friday
Working Day
23
30-MAR-20
Monday
Working Day
23
31-MAR-20
Tuesday
Working Day
23
db<>fiddle here
I got a table named work_schema_items which contains a couple of columns and the important one for this question is varchar column weekday. The contains the following values:
end_time start_time weekday
12:00 06:00 Monday
14:30 12:30 Monday
15:00 14:45 Monday
18:00 15:00 Monday
21:00 18:30 Monday
23:00 21:15 Monday
23:59 23:15 Monday
12:00 06:00 Tuesday
14:30 12:30 Tuesday
15:00 14:45 Tuesday
18:00 15:00 Tuesday
21:00 18:30 Tuesday
23:00 21:15 Tuesday
23:59 23:15 Tuesday
12:00 06:00 Wednesday
14:30 12:30 Wednesday
15:00 14:45 Wednesday
18:00 15:00 Wednesday
21:00 18:30 Wednesday
23:00 21:15 Wednesday
23:59 23:15 Wednesday
12:00 06:00 Thursday
14:30 12:30 Thursday
15:00 14:45 Thursday
18:00 15:00 Thursday
21:00 18:30 Thursday
23:00 21:15 Thursday
23:59 23:15 Thursday
12:00 06:00 Friday
14:30 12:30 Friday
15:00 14:45 Friday
18:00 15:00 Friday
21:00 18:30 Friday
23:00 21:15 Friday
23:59 23:15 Friday
When I run the following sql query:
select
t.date,
t.weekday,
work_schema_items.weekday
from (
select
dd::date as date,
to_char(dd, 'Day')::varchar as weekday
from
generate_series('2019-12-08'::timestamp, '2019-12-16'::timestamp, '1 day'::interval) dd
) as t
left join work_schema_items on t.weekday = work_schema_items.weekday
order by date
I get this result:
2019-12-08 Sunday NULL
2019-12-09 Monday NULL
2019-12-10 Tuesday NULL
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-12 Thursday NULL
2019-12-13 Friday NULL
2019-12-14 Saturday NULL
2019-12-15 Sunday NULL
2019-12-16 Monday NULL
What I'm expecting is to get the weekday value for every day just like I do with Wednesday. How come only Wednesday is properly joined? What am I doing wrong?
Thanks
I found the solution.
char is a fixed length datatype and Wednesday is the longest weekday string. It keeps its width even if I did convert it to varchar which resulted in that I tried to join "Monday " to "Monday".
A simple TRIM() solves the problem:
select
t.date,
t.weekday,
work_schema_items.weekday
from (
select
dd::date as date,
TRIM(to_char(dd, 'Day')::varchar) as weekday
from
generate_series('2019-12-08'::timestamp, '2019-12-16'::timestamp, '1 day'::interval) dd
) as t
left join work_schema_items on t.weekday = work_schema_items.weekday
order by date
I am attempting to change the start of the week of a data set from Monday to the previous Friday. The overall data will be aggregated to a week level to look like this.
Week 1
Friday,
Saturday,
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday
The best I have come up with to do this is a case statement which sets Friday, Saturday and Sunday to next week's First day of the week (the system first day is Monday and last day is Sunday).
SELECT TRANSACTIONDATE,
CASE
WHEN TO_CHAR(TRANSACTIONDATE, 'DAY') IN ('FRIDAY', 'SATURDAY',
'SUNDAY') THEN (TRUNC(TRANSACTIONDATE, 'IW')+7)
ELSE TRUNC(TRANSACTIONDATE, 'IW')
END AS TEST
FROM TRANSACTIONS
My logic for this code is: if Fri, Sat or Sun then find the first day of the week and add 7 returning next week's first day of the week.
The problem is that the statement "TRUNC(TRANSACTIONDATE, 'IW')+7" is not adding 7 days to the week start.
When I query
select "TRUNC(TRANSACTIONDATE, 'IW')+7" from transactions
I get the next weeks week start which is correct.
This way all the days from Friday to Thursday are under the same week number.
Any ideas what's going wrong or if theres a better way to accomplish what I'm after?
Thanks,
Tom
Edit**
The first data set is what I would like at achieve,
Date Day Week
4/1/2018 Monday 1
4/2/2018 Tuesday 1
4/3/2018 Wednesday 1
4/4/2018 Thursday 1
4/5/2018 Friday 2
4/6/2018 Saturday 2
4/7/2018 Sunday 2
4/8/2018 Monday 2
4/9/2018 Tuesday 2
4/10/2018 Wednesday 2
4/11/2018 Thursday 2
So above you can see I want Firday/Saturday/Sunday to fall into the next week.
This is the current system dates/weeks does,
Date Day Week
4/1/2018 Monday 1
4/2/2018 Tuesday 1
4/3/2018 Wednesday 1
4/4/2018 Thursday 1
4/5/2018 Friday 1
4/6/2018 Saturday 1
4/7/2018 Sunday 1
4/8/2018 Monday 2
4/9/2018 Tuesday 2
The problem is TO_CHAR(TRANSACTIONDATE, 'DAY')
When you use 'DAY' then the weekday name is padded with space characters. Try SELECT '<'||TO_CHAR(DATE '2018-05-07', 'DAY')||'>' from dual; to see the effect.
Function TO_CHAR(..., 'DAY') returns the weekday name according to current user session NLS_DATE_LANGUAGE settings. This might be english or not.
Change your expression for example to
TO_CHAR(TRANSACTIONDATE, 'fmDAY', 'NLS_DATE_LANGUAGE=american') IN ('FRIDAY', 'SATURDAY', 'SUNDAY')
I'm looking to find the same day last year in oracle sql. For example Wednesday, March 16, 2016 would be Wednesday, March 18, 2015 for last year. So the closest day.
The following code worked good until the current leap year and broke after Feb 29th 2016.
this was my old statement which does not work for all dates:
NEXT_DAY(TRUNC(ADD_MONTHS(date, -12), 'iw')-2, TO_CHAR(date, 'DY'))
Simply subtract 7*52 = 364 days instead :-)
I think this may be correct
SQL Test:
WITH data
AS ( SELECT SYSDATE - (LEVEL - 1) this_year_date,
TO_NUMBER (TO_CHAR (SYSDATE - (LEVEL - 1), 'D'))
this_year_day_of_week,
ADD_MONTHS (SYSDATE - (LEVEL - 1), -12) last_year_date,
TO_NUMBER (
TO_CHAR (ADD_MONTHS (SYSDATE - (LEVEL - 1), -12), 'D'))
last_year_day_of_week
FROM DUAL
CONNECT BY LEVEL <= 300),
crunching
AS (SELECT data.*,
(CASE
WHEN this_year_day_of_week > last_year_day_of_week
THEN
this_year_day_of_week - last_year_day_of_week
WHEN this_year_day_of_week = last_year_day_of_week
THEN
0
ELSE
last_year_day_of_week - this_year_day_of_week
END)
math
FROM data)
SELECT TO_CHAR (crunching.this_year_date, 'yyyy-MM-dd Day') ty_date,
math,
(CASE
WHEN math = 0
THEN
TO_CHAR (last_year_date, 'yyyy-MM-dd Day')
WHEN math > 2
THEN
TO_CHAR ( (last_year_date - math) + 7, 'yyyy-MM-dd Day')
ELSE
TO_CHAR (last_year_date + math, 'yyyy-MM-dd Day')
END)
final_answer
FROM crunching
SQL Fiddle: http://sqlfiddle.com/#!4/9eecb7d/18211
Output:
TY_DATE MATH FINAL_ANSWER
2016-03-17 Thursday 2 2015-03-19 Thursday
2016-03-16 Wednesday 2 2015-03-18 Wednesday
2016-03-15 Tuesday 2 2015-03-17 Tuesday
2016-03-14 Monday 5 2015-03-16 Monday
2016-03-13 Sunday 5 2015-03-15 Sunday
2016-03-12 Saturday 2 2015-03-14 Saturday
2016-03-11 Friday 2 2015-03-13 Friday
2016-03-10 Thursday 2 2015-03-12 Thursday
2016-03-09 Wednesday 2 2015-03-11 Wednesday
2016-03-08 Tuesday 2 2015-03-10 Tuesday
2016-03-07 Monday 5 2015-03-09 Monday
2016-03-06 Sunday 5 2015-03-08 Sunday
2016-03-05 Saturday 2 2015-03-07 Saturday
2016-03-04 Friday 2 2015-03-06 Friday
2016-03-03 Thursday 2 2015-03-05 Thursday
2016-03-02 Wednesday 2 2015-03-04 Wednesday
2016-03-01 Tuesday 2 2015-03-03 Tuesday
2016-02-29 Monday 5 2015-03-02 Monday
2016-02-28 Sunday 6 2015-03-01 Sunday
2016-02-27 Saturday 1 2015-02-28 Saturday
2016-02-26 Friday 1 2015-02-27 Friday
2016-02-25 Thursday 1 2015-02-26 Thursday
2016-02-24 Wednesday 1 2015-02-25 Wednesday
2016-02-23 Tuesday 1 2015-02-24 Tuesday
2016-02-22 Monday 1 2015-02-23 Monday
2016-02-21 Sunday 6 2015-02-22 Sunday
2016-02-20 Saturday 1 2015-02-21 Saturday
2016-02-19 Friday 1 2015-02-20 Friday
2016-02-18 Thursday 1 2015-02-19 Thursday
2016-02-17 Wednesday 1 2015-02-18 Wednesday
How about add_months( [date], -12 ) ?
I have a date table where I have assinged business days. I need to get business from, for example, 1-20 before the next number 1. How can I do that? Here is a smaller verion of my table:
Date Day BusinessDays
2015-05-01 Friday 1
2015-05-02 Saturday 2
2015-05-03 Sunday 2
2015-05-04 Monday 2
2015-05-05 Tuesday 3
2015-05-06 Wednesday 4
2015-05-07 Thursday 5
2015-05-08 Friday 6
2015-05-09 Saturday 7
2015-05-10 Sunday 7
2015-05-11 Monday 7
2015-05-12 Tuesday 8
2015-05-13 Wednesday 9
2015-05-14 Thursday 10
2015-05-15 Friday 11
2015-05-16 Saturday 12
2015-05-17 Sunday 12
2015-05-18 Monday 12
2015-05-19 Tuesday 13
2015-05-20 Wednesday 14
2015-05-21 Thursday 15
2015-05-22 Friday 16
2015-05-23 Saturday 17
2015-05-24 Sunday 17
2015-05-25 Monday 17
2015-05-26 Tuesday 17
2015-05-27 Wednesday 18
2015-05-28 Thursday 19
2015-05-29 Friday 20
*2015-05-30 Saturday 1
*2015-05-31 Sunday 1
*2015-06-01 Monday 1
*2015-06-02 Tuesday 2
*2015-06-03 Wednesday 3
I need to get data from 1 to 20 business days and don't include the numbers that starts again from one (for example exclude rows that have * in front). This needs to be dynamic. Since DayName will change for every number so I can't include that in my where clause.
Let me assume that you have a date in mind, so you want everything from that date to the next "1".
select t.*
from datetable t
where t.date >= '2015-05-01' and
t.date < (select min(t2.date)
from datetable t2
where t2.date > '2015-05-01' and
t2.businessdays = 1
);