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

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;

Related

Sum over defined Week limits

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.

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

Totals by Day of week over a 2 week period for 1 year

Adding the query (so far) and the result....
DECLARE #var_StartDate DATETIME
DECLARE #var_EndDate DATETIME
SET #var_StartDate = '11/25/2017' -- Set the start date
SET #var_EndDate = '11/23/2018'; --Set the end date
SELECT
DATENAME(DW, VTOTALS.APPLYDATE) AS Day,
FORMAT(SUM(TRANSACTIONS), '#,0.') AS Transactions
FROM
VTOTALS
WHERE
APPLYDATE BETWEEN #var_StartDate AND #var_EndDate
GROUP BY
DATENAME(DW, VTOTALS.APPLYDATE)
ORDER BY
CASE
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Sunday' THEN 1
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Monday' THEN 2
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Tuesday' THEN 3
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Wednesday' THEN 4
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Thursday' THEN 5
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Friday' THEN 6
WHEN DATENAME (DW, VTOTALS.APPLYDATE) = 'Saturday' THEN 7
END ASC
Output:
Day Transactions
Sunday 10,697,804
Monday 25,222,976
Tuesday 25,001,258
Wednesday 24,986,845
Thursday 25,039,354
Friday 24,591,728
Saturday 12,087,903
I am looking for transaction totals by day of week over each day of a pay period for a 1 year timeframe. I can get the DOW but want to split into DOW for week 1 and week 2 over the year between 11/25/17 - 11/23/18
Week 1
Sun 1,980
Mon 38,987
Tue 28,132
Wed 30,879
Thu 30,769
Fri 39,902
Sat 41,912
Week 2
Sun 2,280
Mon 37,987
Tue 29,132
Wed 36,879
Thu 39,769
Fri 42,902
Sat 44,912
Any thoughts?
Thanks
You want weeks that start on Sunday, so you can use the mode argument to week. If you just want the values for one year:
select week(dte, 0), sum(total)
from t
where dte >= '2017-01-01' and dte < '2018-01-01' -- or however you define "year"
group by week(dte, 0);
Take the number of days since some given date, and calculate X % 14. This divides the result by 14 and returns the remainder which will be a number in the range 0 through 13. If you want your result to start on a Sunday, then make sure the given date is a Sunday.
create table VTOTALS
(APPLYDATE date,
[TRANSACTIONS] money)
go
set nocount on
declare #Y int = 0
while #Y < 10000
begin
insert into VTOTALS(ApplyDate,Transactions)
values(
DateAdd(day, #Y % 1000,
'2017-01-01T00:00:00.000' ),
(#Y + 314159)%271828 )
set #Y=#Y+1
end
go
DECLARE #var_StartDate DATETIME
DECLARE #var_EndDate DATETIME
SET #var_StartDate = '2017-11-25T00:00:00.000' -- Set the start date
SET #var_EndDate = '2018-11-23T00:00:00.000'; -- Set the end date
with VWeeks as
( select
DateDiff(day,
'1899-12-31T00:00:00.000',
ApplyDate)%14
as ZeroToThirteen,
* from VTOTALS
WHERE
APPLYDATE BETWEEN #var_StartDate AND #var_EndDate )
SELECT
ZeroToThirteen / 7 + 1 as WeekNum,
DateName ( DW, DateAdd ( day,
ZeroToThirteen,
'1899-12-31T00:00:00.000' ) ) as DayName,
FORMAT(SUM(TRANSACTIONS), '#,0.') AS Transactions
FROM
VWeeks
GROUP BY
ZeroToThirteen
ORDER BY
ZeroToThirteen
returns
WeekNum DayName Transactions
----------- ------------------------------ ----------------
1 Sunday 12,307,100
1 Monday 12,307,360
1 Tuesday 12,307,620
1 Wednesday 12,307,880
1 Thursday 12,308,140
1 Friday 12,308,400
1 Saturday 12,308,660
2 Sunday 12,308,920
2 Monday 12,309,180
2 Tuesday 12,309,440
2 Wednesday 12,309,700
2 Thursday 12,309,960
2 Friday 12,310,220
2 Saturday 12,306,840

How to get second Wednesday of the month

I need to know if current_date is the second Wednesday of the month with PostgreSQL.
Can anyone help me?
You can use EXTRACT to find the day of week and compare that to Wednesday (3rd day of week), and then also check that the day of the month is between the 8th and 14th (inclusive), which will make it the second Wednesday:
select extract(dow from current_date) = 3 and
extract(day from current_date) between 8 and 14;
Output (today 7 Sep 2018)
false
Another example to demonstrate it working:
select extract(dow from timestamp '2018-09-12') = 3 and
extract(day from timestamp '2018-09-12') between 8 and 14;
Output
true
extract week day number and month day number then compare with 3 as each Wednesday day will 3 and 2nd Wednesday day month day will be greater than 8 and less than 13 and then use case when
select case when extract(dow from now())=3 and
EXTRACT(DAY FROM now())>7 and EXTRACT(DAY FROM now())<=13
then 'it is 2nd wednesday' else 'not';

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