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

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

Related

How to get 1st and 3rd Saturday and all Sunday between 2 dates using sql

Given a date range, I'd like to return all of the Saturdays and Sundays that fall within that range, with these conditions:
Include Saturdays only if their ordinal position is either the 1st or 3rd Saturday within the month they fall (not within the entire range).
Include all Sundays, along with the ordinal position of that Sunday within the month it falls.
So for example, if the start date is Aug 15, 2021 and the end date is Sep 20, 2021, the output would be:
Dates Saturday Number (in its own month)
---------- ---------------
2021-08-21 3
2021-09-04 1
2021-09-18 3
Dates Sunday Number (in its own month)
---------- ---------------
2021-08-15 3
2021-08-22 4
2021-08-29 5
2021-09-05 1
2021-09-12 2
2021-09-19 3
Then I can take the date range in total (37 days), and subtract the Sundays (6), and the 1st and 3rd Saturdays from each month (3), to end at 28.
Tried this query
DECLARE #sd DATETIME = '2021-08-15' DECLARE #ed DATETIME =
'2021-09-20'
--find first saturday WHILE DATEPART(dw, #sd)<>7 BEGIN SET #sd = DATEADD(dd,1,#sd) END
--get next saturdays ;WITH Saturdays AS (
--initial value SELECT #sd AS MyDate, 1 AS SatNo UNION ALL
--recursive part SELECT DATEADD(dd,7,MyDate) AS MyDate, CASE WHEN SatNo + 1 =6 THEN 1 ELSE SatNo+1 END AS SatNo FROM Saturdays
WHERE DATEADD(dd,7,MyDate)<=#ed
) SELECT * FROM Saturdays WHERE SatNo IN (1,3) OPTION(MAXRECURSION 0)
it does not work properly.
Also Tried this solution
Get number of weekends between two dates in SQL
for calculate week days, but I want only 1st and 3 Saturday and all Sundays
Get a calendar table; it makes this type of business problem a breeze. Here's a simpler one:
CREATE TABLE dbo.Calendar
(
TheDate date PRIMARY KEY,
WeekdayName AS (CONVERT(varchar(8), DATENAME(WEEKDAY, TheDate))),
WeekdayInstanceInMonth tinyint
);
;WITH x(d) AS -- populate with 2020 -> 2029
(
SELECT CONVERT(date, '20200101')
UNION ALL
SELECT DATEADD(DAY, 1, d)
FROM x
WHERE d < '20291231'
)
INSERT dbo.Calendar(TheDate)
SELECT d FROM x
OPTION (MAXRECURSION 0);
;WITH c AS
(
SELECT *, rn = ROW_NUMBER() OVER
(PARTITION BY YEAR(TheDate), MONTH(TheDate), WeekdayName
ORDER BY TheDate)
FROM dbo.Calendar
)
UPDATE c SET WeekdayInstanceInMonth = rn;
Now your query is easy:
DECLARE #start date = '20210815', #end date = '20210920';
SELECT Dates = TheDate,
[Saturday Number] = WeekdayInstanceInMonth
FROM dbo.Calendar
WHERE TheDate >= #start
AND TheDate <= #end
AND WeekdayName = 'Saturday'
AND WeekdayInstanceInMonth IN (1,3);
SELECT Dates = TheDate,
[Sunday Number] = WeekdayInstanceInMonth
FROM dbo.Calendar
WHERE TheDate >= #start
AND TheDate <= #end
AND WeekdayName = 'Sunday';
Results (db<>fiddle example here):
Dates Saturday Number
---------- ---------------
2021-08-21 3
2021-09-04 1
2021-09-18 3
Dates Sunday Number
---------- ---------------
2021-08-15 3
2021-08-22 4
2021-08-29 5
2021-09-05 1
2021-09-12 2
2021-09-19 3
And to get just the number 28:
DECLARE #start date = '20210815', #end date = '20210920';
SELECT DATEDIFF(DAY, #start, #end) + 1
-
(SELECT COUNT(*)
FROM dbo.Calendar
WHERE TheDate >= #start
AND TheDate <= #end
AND WeekdayName = 'Saturday'
AND WeekdayInstanceInMonth IN (1,3))
-
(SELECT COUNT(*)
FROM dbo.Calendar
WHERE TheDate >= #start
AND TheDate <= #end
AND WeekdayName = 'Sunday');
Assuming datefirst is set for Sunday:
(
day(dt) +
datepart(weekday, dateadd(dt, 1 - day(dt))) % 7
) / 7 as SaturdayNumber,
(
day(dt) - 1 +
datepart(weekday, dateadd(dt, 1 - day(dt)))
) / 7 as SundayNumber
For all dates this essentially computes a week number (0-5) within the month, relative to Saturday/Sunday.

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

Get 'number week of the day'?

I have a date like '2020-09-17' and I want this: 'Third Tuesday - 2020-09-17' which 'Third' represents that 17/09 is the third Tuesday from September.
Any ideas to solve this by using SQL Server?
I cobbled this function together just now. It only works when SET DATEFIRST 1. Modifying this function to work with calendars where Monday is not the first day of the week is an exercise for the reader (caution: doing so is non-trivial).
SET DATEFIRST 1; -- Set Monday as the first day-of-week.
CREATE FUNCTION dbo.GetDayOfWeekInMonth( #date date )
RETURNS int
AS
BEGIN
--SET DATEFIRST 1; -- can't use this inside a function
DECLARE #dayOfMonth int = DATEPART( day , #date );
DECLARE #dayOfWeek int = DATEPART( weekday, #date );
DECLARE #startOfMonth date = DATEFROMPARTS( YEAR( #date ), MONTH( #date ), 1 );
DECLARE #startOfMonthDayOfWeek int = DATEPART( weekday, #startOfMonth );
DECLARE #weekNumber int = #dayOfMonth / 7;
DECLARE #dayOfWeekInMonth int = CASE WHEN #startOfMonthDayOfWeek > #dayOfWeek THEN #weekNumber ELSE ( #weekNumber + 1 ) END;
RETURN #dayOfWeekInMonth
END
Example:
So running this:
SET DATEFIRST 1
DECLARE #t TABLE ( Dt date NOT NULL, DoW int NOT NULL, DoWName nvarchar(20) NOT NULL, DoWoM int NOT NULL );
DECLARE #d int = 1
WHILE #d <= 30
BEGIN
DECLARE #dt date = DATEFROMPARTS( 2020, 9, #d );
INSERT INTO #t ( Dt, DoW, DoWName, DoWoM )
VALUES (
#dt,
DATEPART( weekday, #dt ),
DATENAME( weekday, #dt ),
dbo.GetDayOfWeekInMonth( #dt )
);
SET #d = #d + 1
END;
SELECT
*,
CASE DoWoM
WHEN 1 THEN CONCAT( 'First ' , DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 2 THEN CONCAT( 'Second ', DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 3 THEN CONCAT( 'Third ' , DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 4 THEN CONCAT( 'Fourth ', DoWName, ' of ', DATENAME( month, Dt ) )
WHEN 5 THEN CONCAT( 'Fifth ' , DoWName, ' of ', DATENAME( month, Dt ) ) ELSE NULL
END AS [Text]
FROM
#t;
Gives me this output:
Dt DoW DoWName DoWoM Text
2020-09-01 2 Tuesday 1 First Tuesday of September
2020-09-02 3 Wednesday 1 First Wednesday of September
2020-09-03 4 Thursday 1 First Thursday of September
2020-09-04 5 Friday 1 First Friday of September
2020-09-05 6 Saturday 1 First Saturday of September
2020-09-06 7 Sunday 1 First Sunday of September
2020-09-07 1 Monday 1 First Monday of September
2020-09-08 2 Tuesday 2 Second Tuesday of September
2020-09-09 3 Wednesday 2 Second Wednesday of September
2020-09-10 4 Thursday 2 Second Thursday of September
2020-09-11 5 Friday 2 Second Friday of September
2020-09-12 6 Saturday 2 Second Saturday of September
2020-09-13 7 Sunday 2 Second Sunday of September
2020-09-14 1 Monday 2 Second Monday of September
2020-09-15 2 Tuesday 3 Third Tuesday of September
2020-09-16 3 Wednesday 3 Third Wednesday of September
2020-09-17 4 Thursday 3 Third Thursday of September
2020-09-18 5 Friday 3 Third Friday of September
2020-09-19 6 Saturday 3 Third Saturday of September
2020-09-20 7 Sunday 3 Third Sunday of September
2020-09-21 1 Monday 3 Third Monday of September
2020-09-22 2 Tuesday 4 Fourth Tuesday of September
2020-09-23 3 Wednesday 4 Fourth Wednesday of September
2020-09-24 4 Thursday 4 Fourth Thursday of September
2020-09-25 5 Friday 4 Fourth Friday of September
2020-09-26 6 Saturday 4 Fourth Saturday of September
2020-09-27 7 Sunday 4 Fourth Sunday of September
2020-09-28 1 Monday 4 Fourth Monday of September
2020-09-29 2 Tuesday 5 Fifth Tuesday of September
2020-09-30 3 Wednesday 5 Fifth Wednesday of September
I had to change the implementation for this code below because the previous solution wasn't working with certain date's such as 2020-07-13 when thar return 1 instead 2 as expected. For sure i need some "tunning hands" in that but for a while i'm using to populate a calendar table.
create function dbo.getdayofweekinmonth( #date date )
returns int
as
begin
declare #dayofweek int = (datepart(dw, #date) + ##datefirst + 6 - 1) % 7 + 1;
declare #startofmonth date = datefromparts( year( #date ), month( #date ), 1 );
declare #month_days as table (d int) -- d as day number
while #startofmonth <= #date
begin
insert into #month_days values ((datepart(dw, #startofmonth) + ##datefirst + 6 - 1) % 7 + 1);
select #startofmonth = dateadd(day, 1, #startofmonth);
end
return (select count(*) from #month_days where d = #dayofweek)
end
For higher Performance, it is better to use Date Dimension Table and Join it with Your own table (Date Dimension is a table that has one record per each day and contains all the information you need about a certain date )

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

Relative days in SQL

I have a requirement to create a view on top of DimCalendar/DimDate dimension to get following [Relative Days] column -
If today is 10/6 - Friday, then my relative days is 0. Tomorrow is Saturday which is a weekend the we should not consider it as a Business day. Hence it would still be 0. Same thing applies for Sunday. From Monday on wards it will increase.
If we go back, the number should be negative. It should also consider weekends.
Can someone help me to write a SQL code to populate Relative Days column that would change based on today?
UPDATE
I tried this but didn't work.
cast((DATEDIFF(dd, GETDATE(), c.Date) + 1) - (DATEDIFF(wk, GETDATE(), c.Date) * 2) -(CASE WHEN DATEPART(dw, GETDATE()) = 1 THEN 1 ELSE 0 END) - (CASE WHEN DATEPART(dw, c.Date) = 7 THEN 1 ELSE 0 END) as int) [Relative Days]
Thanks
You can use a cumulative sum:
select cal.*,
(cume_days -
max(case when caldate = '2017-10-06' then cume_day end) over ()
) as relative_days
from (select cal.*,
sum(case when day in ('Saturday', 'Sunday' then 0 else 1 end) over
(order by caldate) as cume_days
from cal
) c;
However, you cannot make this a column in the table -- it changes every day. You can, however, put the calculation in a view.
You can use this query for the calculation
DECLARE #Today DATE= '20171006'
SET DATEFIRST 1
;WITH CTE AS
(
SELECT CalendarDate,
WD = CASE WHEN DATEPART(WEEKDAY,CalendarDate) IN (6,7) THEN 0 ELSE DATEPART(WEEKDAY,CalendarDate) END ,
W = DATEPART(WEEK,CalendarDate) ,
BeforeAfterConstant = CASE WHEN CalendarDate < #Today THEN 1 ELSE 0 END
FROM #Calendar
)
SELECT
CalendarDate,
[Day] = DATENAME ( WEEKDAY, CalendarDate ),
RelativeDays =
( 5 - DATEPART( WEEKDAY, #Today ) )
+ ( (W - DATEPART( WEEK, #Today ) - ( CASE WD WHEN 0 THEN 0 ELSE 1 END ) ) * 5 )
+ CASE WHEN WD = 0 THEN BeforeAfterConstant ELSE WD END
FROM CTE
Result:
CalendarDate Day RelativeDays
------------ ------------------------------ ------------
2017-09-26 Tuesday -8
2017-09-27 Wednesday -7
2017-09-28 Thursday -6
2017-09-29 Friday -5
2017-09-30 Saturday -4
2017-10-01 Sunday -4
2017-10-02 Monday -4
2017-10-03 Tuesday -3
2017-10-04 Wednesday -2
2017-10-05 Thursday -1
2017-10-06 Friday 0
2017-10-07 Saturday 0
2017-10-08 Sunday 0
2017-10-09 Monday 1
2017-10-10 Tuesday 2
2017-10-11 Wednesday 3
2017-10-12 Thursday 4
2017-10-13 Friday 5
2017-10-14 Saturday 5
2017-10-15 Sunday 5
2017-10-16 Monday 6