How do we convert 2018-12-31 as Week 1 of 2019 in SQL? - sql

Using CONCAT(TO_CHAR(T.order_create_date,'yyyy')," ",WEEKOFYEAR(T.order_create_date)) returns 2018-12-31 as 2018-1.

The first week of each year starts on the first Monday on or before January 4 of that year, so that the year begins from December 28 of the prior year through January 4 of the current year.
SELECT(DATEPART(dy,DATEADD(dd,DATEDIFF(dd,'17530101',#SomeDate)/7*7,'17530104'))+6)/7;

Related

SQL BigQuery: How to populate dates from rows cycle_base and cycle_interval

I'm having trouble populating dates with variable cycle_base (day of week) and cycle_interval (days) columns in Google BigQuery SQL.
The idea is to populate a date array for 2022 for each product where the dates fall within the valid_from and valid_to dates and where the dates are generated with the respective cycle_interval
A snippet from my data looks like this:
cycle_base
valid_from
valid_to
cycle_interval
product
2016-09-19
2020-04-20
2022-12-31
7
A
2018-12-17
2020-01-27
2022-12-31
28
B
2019-12-30
2020-01-27
2022-12-31
56
C
I tried generating a date array and then joining those dates on the DAYOFWEEK, which ofcourse only works for rows with a interval of 7 days. But I can't seem to find a way to achieve the above with the other intervals.
Edit
Expected data for 2022:
The cycle_base represents the day of the week. The exact date is irrelevant really. Edit: The date represents the starting point from which to interval the weeks.
Product A starts on monday for every week.
Product B starts on monday for every 3 weeks.
Product C starts on monday for every 8 weeks.
date
product
dayofweek
cycle_interval
2022-01-03
A
monday
7
2022-01-10
A
monday
7
...
...
...
...
2022-01-03
B
monday
28
2022-01-17
B
monday
28
...
...
...
...
2022-01-03
C
monday
56
2022-02-21
C
monday
56
...
...
...
...
Hope someone can point me in the right direction :)
Thanks in advance,
Glenn

Create a table to have only working days excluding weekends and public holidays

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

Logic to get dynamic date range in query for Fiscal Year

I have a requirement to select data for different date ranges, depending one the current month it is run on. I have a Stored Procedure that takes in a user supplied Date i.e. 04/06/2020 into the variable #PPE. Based on the Month portion of this date, I need to query back varying ranges as in a Fiscal Year (July 1 - June 30th) follows: I am using the example using a 2020 Financial Year.
MONTH(#PPE) Date Range to Query
July 07/01/2019 - 07/01/2019
August 07/01/2019 - 08/31/2019
September 07/01/2019 - 09/30/2019
October 07/01/2019 - 09/30/2019
November 07/01/2019 - 09/30/2019
December 07/01/2019 - 09/30/2019
January 07/01/2019 - 12/31/2019
February 07/01/2019 - 12/31/2019
March 07/01/2019 - 12/31/2019
April 07/01/2019 - 03/31/2020
May 07/01/2019 - 03/31/2020
June 07/01/2019 - 03/31/2020
Then Starting next Fiscal Year (2021) it would go as follows, and onwards...
MONTH(#PPE) Date Range to Query
July 07/01/2020 - 07/01/2020
August 07/01/2020 - 08/31/2020
September 07/01/2020 - 09/30/2020
October 07/01/2020 - 09/30/2020
November 07/01/2020 - 09/30/2020
December 07/01/2020 - 09/30/2020
January 07/01/2020 - 12/31/2020
February 07/01/2020 - 12/31/2020
March 07/01/2020 - 12/31/2020
April 07/01/2019 - 03/31/2021
May 07/01/2019 - 03/31/2021
June 07/01/2019 - 03/31/2021
I started with this query , but I'm having trouble manipulating the correct FISCAL_YEAR to put in, depending on what the month of the #PPE date is, because it spans 2 years between April and June.
PERIOD represents the Fiscal Month number i.e. July = 1 , August = 2, ....June = 12
DECLARE #PPE datetime; SET #PPE = '04/06/2020'
SELECT COMPANY, DEPTID, FISCAL_YEAR, PERIOD, GH_REPORTID, SUM(GH_HOURS), SUM(GH_DOLLARS)
FROM PS_GH_SLT_ACTUALS
WHERE DEPTID = 55650000
AND GH_REPORTID = 'BA'
AND PERIOD <= CASE WHEN MONTH(#PPE) BETWEEN 1 AND 3 THEN 12
WHEN MONTH(#PPE) BETWEEN 4 AND 6 THEN 3
WHEN MONTH(#PPE) BETWEEN 7 AND 9 THEN 6
WHEN MONTH(#PPE) BETWEEN 10 AND 12 THEN 9
END
-- AND PERIOD <= 7 ???
AND FISCAL_YEAR = CASE WHEN MONTH(#PPE) BETWEEN 1 AND 3 THEN YEAR(#PPE)
WHEN MONTH(#PPE) BETWEEN 4 AND 6 THEN ....???
GROUP BY COMPANY, DEPTID, FISCAL_YEAR, PERIOD, GH_REPORTID
If your fiscal year is already in the format, then you can use the following and condition:
FISCAL_YEAR = CASE WHEN MONTH(#PPE) BETWEEN 1 AND 6 THEN YEAR(#PPE)
ELSE YEAR(#PPE)+1 END
The above condition should work under the assumption that, Jul 2019 to Jun 2020 is called as Fiscal year 2020, as per your data. Hope this helps.

Date calculation not working in Oracle SQL Case Statement?

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')

SQL - pick current date from machine and compare the year

Scenario 1: Current Year
Always code needs to pick
The last Sunday of January for the current year. For ex(31-01-2016)
Current code - picks 1st of Jan 2016
convert(date,DATEADD(yy, DATEDIFF(yy, 0, getdate()), 0))
Scenario 2: Last Year
Always code needs to pick
The last Sunday of January for the Previous year. For ex(01-02-2015)
Current code - picks 1st of Jan 2015
convert(date,DATEADD(yy, DATEDIFF(yy, 0, dateadd(YEAR, - 1, getdate())), 0))
Instead of hard coding the date. I would like to pick date from machine and compare.
Week start from Sunday and ends Saturday. Any help please?
-- Sample Demonstrative Data/Test Results
Declare #YourTable table (SomeDate date)
Insert Into #YourTable values ('2000-06-15'),('2001-06-15'),('2002-06-15'),('2003-06-15'),('2004-06-15'),('2005-06-15'),('2006-06-15')
,('2007-06-15'),('2008-06-15'),('2009-06-15'),('2011-06-15'),('2012-06-15'),('2013-06-15'),('2014-06-15'),('2015-06-15'),('2016-06-15')
,('2017-06-15'),('2018-06-15'),('2019-06-15'),('2020-06-15')
-- To Confirm Results
Select Year = year(SomeDate)
,LastSundayDate = DateAdd(DD,-DatePart(DW,DateFromParts(Year(SomeDate),12,31))+1,DateFromParts(Year(SomeDate),12,31))
,LastSundayName = DateName(DW,DateAdd(DD,-DatePart(DW,DateFromParts(Year(SomeDate),12,31))+1,DateFromParts(Year(SomeDate),12,31)))
From #YourTable
Returns
Year LastSundayDate LastSundayName
2000 2000-12-31 Sunday
2001 2001-12-30 Sunday
2002 2002-12-29 Sunday
2003 2003-12-28 Sunday
2004 2004-12-26 Sunday
2005 2005-12-25 Sunday
2006 2006-12-31 Sunday
2007 2007-12-30 Sunday
2008 2008-12-28 Sunday
2009 2009-12-27 Sunday
2011 2011-12-25 Sunday
2012 2012-12-30 Sunday
2013 2013-12-29 Sunday
2014 2014-12-28 Sunday
2015 2015-12-27 Sunday
2016 2016-12-25 Sunday
2017 2017-12-31 Sunday
2018 2018-12-30 Sunday
2019 2019-12-29 Sunday
2020 2020-12-27 Sunday