Sum over defined Week limits - sql

I have a rolling date with associated hours. I want to sum the hours over my defined 7-day week range of Saturday to Friday.
So I need to define any date as a week beginning Saturday, week ending Friday and sum over this range.
The table is in the form of:
Date
Day
Hours
2021-06-12
Saturday
3
2021-06-18
Friday
3
2021-06-21
Monday
1
2021-06-22
Tuesday
2
Grouping the above table into Saturday-Friday Week sums.
Saturday
Friday
Total_Hours
2021-06-12
2021-06-18
6
2021-06-19
2021-06-25
3

You can use date functions to get for each date (other than Saturday) the previous Saturday which is the start of the week it belongs too and group by that:
WITH cte AS (
SELECT *, DATEADD(day, -DATEPART(dw, Date) % 7, Date) Saturday
FROM tablename
)
SELECT Saturday,
DATEADD(day, 6, Saturday) Friday,
SUM(Hours) Total_Hours
FROM cte
GROUP BY Saturday
See the demo.
This code works in SQL Server but similar logic and functions can be used for other databases.

You don't have to tie this to datepart() or datename(), which in turn depends on DATEFIRST (alas!).
Instead, you can use date arithmetic. This in turn depends on the fact that 0 date is a Monday. But that is not configurable (as far as I know).
So:
select v.week as saturday, dateadd(day, 6, v.week) as friday,
sum(hours)
from t cross apply
(values (dateadd(day, 7*datediff(week, 0, dateadd(day, 1, t.date)) - 2, 0))
) v(week)
group by v.week
order by v.week;
Here is a db<>fiddle.

Related

Getting week of the month. Week should start on Monday and end a Sunday

I need to add new business wee to my dim_date actually i have week of the month that is counting every 7 days of month as the table bellow.
Date
Week of month
day_of_week
01/04/2022
1
Friday
02/04/2022
1
Saturday
03/04/2022
1
Sunday
04/04/2022
1
Monday
05/04/2022
1
Tuesday
06/04/2022
1
Wednesday
07/04/2022
1
Thursday
08/04/2022
2
Friday
09/04/2022
2
Saturday
10/04/2022
2
Sunday
But for this business week column the week should start on Monday and end at Sunday, even if the first week is only one day(when a month starts at Sunday), but if the month starts on Friday, I should consider it as the first week of the month.
Date
Week of month
day_of_week
01/04/2022
1
Friday
02/04/2022
1
Saturday
03/04/2022
1
Sunday
04/04/2022
2
Monday
05/04/2022
2
Tuesday
06/04/2022
2
Wednesday
07/04/2022
2
Thursday
08/04/2022
2
Friday
09/04/2022
2
Saturday
10/04/2022
2
Sunday
Do you have any suggestion to calculate this?
Thank you
This query gets the number of the week from 2002-04-01 to 2002-04-19. The week start from monday and finishes on sunday. You can see this example:
with sample_data as (
SELECT date FROM UNNEST(generate_timestamp_array('2022-04-01', '2022-04-19', INTERVAL 1 DAY)) as date
)
select
date
, extract(week(MONDAY) from date)-(extract(MONTh from date)-1)*4 AS days_diff
, FORMAT_DATE('%A', date)
from sample_data
You can see the result.
You need to use EXTRACT function.
i hope that this solution i figured out could help you in the future or we can discuss and imporve this solution:
WITH sample_data AS (SELECT
date,
EXTRACT(WEEK FROM date) AS week_of_year,
DATE_TRUNC(date, MONTH) AS FIRST_DAY_OF_MONTH
FROM (SELECT date
FROM UNNEST(GENERATE_TIMESTAMP_ARRAY('2022-04-01', '2022-04-19', INTERVAL 1 DAY)) AS date))
SELECT
date,
FORMAT_DATE('%A', date) as day_name,
CASE
WHEN CAST(EXTRACT(WEEK(MONDAY) FROM d.date) AS INT) = 0 AND d.WEEK_OF_YEAR IN (52, 53) THEN 1
WHEN CAST(EXTRACT(WEEK(MONDAY) FROM d.FIRST_DAY_OF_MONTH) AS INT) = 0 THEN EXTRACT(WEEK(MONDAY) FROM d.date) + 1
ELSE (d.WEEK_OF_YEAR - CAST(EXTRACT(WEEK(MONDAY) FROM d.FIRST_DAY_OF_MONTH) AS INT)) + 1
END AS BUSINESS_WEEK_OF_MONTH
FROM sample_data d;

Get week period based on week number, month and year sql

I need to get the first day and the last day of the week based on the number of the week, year and month
My week starts on saturday and finish in friday
Example:
Year: 2020
Week: 45
Normal period of week: First day: 2020-10-31 ~ Last day: 2020-11-06
I need return something like
October: First day: 2020-10-31 ~ last day: 2020-10-31
November: First day 2020-11-01 ~ last day: 2020-11-06
my query to return last day of week:
select DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5 as lastDayOfWeek
my query to return first day of week
SELECT WeekStart = DATEADD(DAY,
(CEILING(DATEPART(DAY, DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5) / 7.0) - 1) * 7,
DATEADD(MONTH, DATEDIFF(MONTH, 0,DATEADD (WEEK, #PcpSemana, DATEADD (YEAR, ('20' + LEFT(#PcpPeriodo,2))-1900, 0)) - 5), 0));
I'm using SET DATEFIRST 6
I can't evolve much
PcpPeriodo contains YYMM ( 2011) = 2020 / 11 )
PcpSemana contains weeknumber (45) (01 ~ 53)
I am not sure what your data looks like, but if you have the first day of the week, you can split it among months as:
select weeks.*
from (values (convert(date, '2020-10-31'))) w(weekstart) cross apply
(values (dateadd(day, 6, w.weekstart), eomonth(w.weekstart))
) v(weekend, eom) cross apply
(values (w.weekstart,
case when v1.weekend <= v1.eom then v1.weekend else v1.eom end
),
(case when v1.weekend > v1.eom then dateadd(day, 1, v1.eom) end,
case when v1.weekend > 1.eom then v1.weekend
)
) weeks(weekstart, weekend)
where weeks.weekstart is not null;
This is using apply as a way of storing intermediate results, such as the last day of the month and when the week ends.
DECLARE #d datetime;
SET DATEFIRST 6;
SET #d = '2020-11-01';
WITH weektest as (
select #d as d
union all
select DATEADD(DAY,1,d) from weektest where d<='2020-11-6'
)
SELECT
d,
DATEPART(week, d),
DATEPART(weekday,d),
DATENAME(weekday,d)
from weektest;
output:
d
----------------------- ----------- ----------- ------------------------------
2020-11-01 00:00:00.000 45 2 Sunday
2020-11-02 00:00:00.000 45 3 Monday
2020-11-03 00:00:00.000 45 4 Tuesday
2020-11-04 00:00:00.000 45 5 Wednesday
2020-11-05 00:00:00.000 45 6 Thursday
2020-11-06 00:00:00.000 45 7 Friday
2020-11-07 00:00:00.000 46 1 Saturday

How to find the 3rd business day of a month (Saturday and Sunday are weekend)?

I need to find next final pay period under few conditions. The maturity is 3 months, but when the last payday is till the 3st business day of the current month. Оtherwise is the maturity 4 months. And Saturday and Sunday are not working days. For example: now in August 2019 are 3.08 and 4.08 not working day and when the customer pay the tax till 5.08(Monday - this is the 3st business day for a August) the next payday period is till end of Oktober 2019. Otherwise when the day is 6.08 is the period till end of November
IF #Schema = '1000'
BEGIN
SET #PayPeriod = 3
IF #Payday < DATEADD(DAY, CASE (DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, #Payday), 0)) + ##DATEFIRST) % 7
WHEN 6 THEN 2
WHEN 7 THEN 1 ELSE 0 END,
DATEADD(MONTH, DATEDIFF(MONTH, 0, Payday), 3))
SET #PayPeriod = EOMONTH(#Payday, #PayPeriod-1)
ELSE SET #PayPeriod = EOMONTH(#Payday, #PayPeriod)
END
And here is the result. After 06.08.2019 must be the payperiod end of November
2019-08-01 2019-10-31
2019-08-02 2019-10-31
2019-08-03 2019-10-31
2019-08-04 2019-11-30
2019-08-05 2019-11-30 here is the problem!
2019-08-06 2019-11-30
This should work for you:
declare #payday as datetime = '20190602'
;with cte as (
select datefromparts(year(#payday), month(#payday), 1) as monthday
union all
select dateadd(day, 1, monthday)
from cte
where day(monthday) < 10
)
select
case
when count(*) <= 3 then eomonth(#payday, 3)
else eomonth(#payday, 4)
end as MaturityEnd
from cte
where datepart(weekday, monthday) not in (7, 1)
and monthday <= #payday
Here we generate first couple of dates for the same month as in payment date and count business days smaller than payment date. Maturity end date is calculated based on the count of days.
It is not totally clear what you want from your question. I believe what you want is:
Give a date ##DATEFIRST find a date of maturity
3 months later unless
that date falls in the first 3 business days of a month than then
4 months later
Is that correct?
Also what does EOMONTH do? The use of it in your example does not seem to make sense compared to the stated requirements.

SQL: First day of week Monday

I would like to display Monday as the first day of the week and Sunday the last day of the week.
I am using for this report the Report server.
my query:
Select
Datum,
Sum(Prod) as Prod
FROM (
Select
intervaldate as Datum,
Sum(case when TabName = 'Produzierte Dosen' then DisplayUnits else 0 end) as Prod
from vwOeeIntervalCount
where
IntervalDateWeek >= dateadd(wk, datediff(wk, 0, getdate()) - 1, 0)
and IntervalDateWeek < dateadd(wk, datediff(wk, 0, getdate()), 0)
and IntervalDate >= dateadd(day,datediff(day,0,GETDATE())-6,0)
AND IntervalDate < dateadd(day,datediff(day,0,GETDATE()),0)
and CalculationName = 'Packaging'
group by intervaldate
)c
group by Datum
Here the result:
Date |Prod
2018-02-25 00:00:00.000 |1836528
2018-02-26 00:00:00.000 |8131127,99999999
EDIT:
Sorry here is my question.
I would like to display the Monday as the first day of the week. My query displays the Sunday as the first day of the week.
How can I do that?
By default MS SQL Server has configured sunday as first day of a week.
You can set the server config for the first day of a week to any day with the following command:
SET DATEFIRST { number | #number_var }
Value First day of the week is
1 Monday
2 Tuesday
3 Wednesday
4 Thursday
5 Friday
6 Saturday
7 (default, U.S. English) Sunday
Source: https://learn.microsoft.com/en-us/sql/t-sql/statements/set-datefirst-transact-sql
you can use this to the current week:
/*-- Week Start
--1->Sunday --2->Monday....*/
SELECT CAST(DATEADD(dd, -(DATEPART(dw, GETDATE()))+2, GETDATE()) AS DATE) [WeekStart],
CAST(DATEADD(dd, 8-(DATEPART(dw, GETDATE())), GETDATE()) AS DATE) [WeekEnd]
/*-- Week End
--7->Saturday --8-> Sunday...*/
Running this today will produce this result:
WeekStart WeekEnd
---------- ----------
2018-02-26 2018-03-04
if you have dates in your table, you can use them instead of the GETDATE()

How to select every Monday date and every Friday date in the year

basically I want to be able to select monday and friday for every week in the year.
So for example this week coming i want 9/29/2014 and 10/3/2014, but i want this for every week in the year.
Here's one way (you might need to check which day of the week is setup to be the first, here I have Sunday as the first day of the week)
You can use a table with many rows (more than 365) to CROSS JOIN to in order to get a run of dates (a tally table).
My sys columns has over 800 rows in, you could use any other table or even CROSS JOIN a table onto itself to multiply up the number of rows
Here I used the row_number function to get a running count of rows and incremented the date by 1 day for each row:
select
dateadd(d, row_number() over (order by name), cast('31 Dec 2013' as datetime)) as dt
from sys.columns a
With the result set of dates now, it's trivial to check the day of week using datepart()
SELECT
dt,
datename(dw, dt)
FROM
(
select
dateadd(d, row_number() over (order by name), cast('31 Dec 2013' as datetime)) as dt
from
sys.columns a
) as dates
WHERE
(datepart(dw, dates.dt) = 2 OR datepart(dw, dates.dt) = 6)
AND dt >= '01 Jan 2014' AND dt < '01 Jan 2015'
Edit:
Here's an example SqlFiddle
http://sqlfiddle.com/#!6/d41d8/21757
Edit 2:
If you want them on the same row, days of the week at least are constant, you know Friday is always 4 days after Monday so do the same but only look for Mondays, then just add 4 days to the Monday...
SELECT
dt as MonDate,
datename(dw, dt) as MonDateName,
dateadd(d, 4, dt) as FriDate,
datename(dw, dateadd(d, 4, dt)) as FriDateName
FROM
(
select
dateadd(d, row_number() over (order by name), cast('31 Dec 2013' as datetime)) as dt
from
sys.columns a
) as dates
WHERE
datepart(dw, dates.dt) = 2
AND dt >= '01 Jan 2014' AND dt < '01 Jan 2015'
AND dt >= '01 Jan 2014' AND dt < '01 Jan 2015'
Example SqlFiddle for this:
http://sqlfiddle.com/#!6/d41d8/21764
(note that only a few rows come back because sys.columns is quite small on the SqlFiddle server, try another system table if this is a problem)
You can use a suitable table with numbers, like the master..spt_values table as basis for the range generation:
;WITH dates AS (
SELECT DATEADD(DAY,number,CAST('2014-01-01' AS DATE)) d
FROM master..spt_values WHERE TYPE = 'p'
AND number < 366
)
SELECT
Week = DATEPART(WEEK, d),
DayOfWeek = DATENAME(dw, d),
Date = d
FROM dates
WHERE DATENAME(dw, d) IN ('Monday', 'Friday')
-- or use datepart instead as datename might be specific to language
-- WHERE DATEPART(dw, d) IN (2,6)
Sample output:
Week DayOfWeek Date
----------- ------------------------------ ----------
1 Friday 2014-01-03
2 Monday 2014-01-06
2 Friday 2014-01-10
3 Monday 2014-01-13
3 Friday 2014-01-17
4 Monday 2014-01-20
4 Friday 2014-01-24
5 Monday 2014-01-27
5 Friday 2014-01-31
SELECT extract(isodow from "date_source") as datee 1-monday 7-sunday
and then in WHERE write datee IN ('1','2'....)