Find date for last four sundays - sql

Namely what I need is:
The key over here is that it does change the dates every week, from last Sunday, to 2nd last Sunday and so on, so that it is dynamic.
Will appreciate if someone can help.
CASE
WHEN f.[STARTDATE] = last week Sunday (03/06) THEN '1 week ago'
WHEN f.[STARTDATE] = last 2 week Sunday (02/27) THEN '2 weeks ago'
WHEN f.[STARTDATE] = last 3 week Sunday (02/20) THEN '3 week ago'
WHEN f.[STARTDATE] = last 4 week Sunday (02/13) THEN '4 week ago'
END AS 'STARTDATE'
Thank you

First you need to get nearest Sunday before you can subtract 7, 14, 21 and 28 days from it. The simplest way is to check current day of week and calculate an offset: 0 for Sunday, 1 for Monday and so on:
with cte as (
select offsett = case datename(weekday, cast(current_timestamp as date))
when 'sunday' then 0
when 'monday' then 1
when 'tuesday' then 2
when 'wednesday' then 3
when 'thursday' then 4
when 'friday' then 5
when 'saturday' then 6
end
)
select case
when f.[startdate] = dateadd(day, -cte.offsett - 7, cast(current_timestamp as date)) then '1 week ago'
when f.[startdate] = dateadd(day, -cte.offsett - 14, cast(current_timestamp as date)) then '2 week ago'
when f.[startdate] = dateadd(day, -cte.offsett - 21, cast(current_timestamp as date)) then '1 week ago'
when f.[startdate] = dateadd(day, -cte.offsett - 28, cast(current_timestamp as date)) then '2 week ago'
end
from f
cross join cte

Related

I need data from Prior Monday to saturday when i run my interface on Tuesday at 1:30am. utlized a example query

select *
from VP_TIMESHTPUNCHV42
where (EVENTDATE>=getdate()-8) AND (EVENTDATE <=getdate()-3)
AND PERSONNUM = '668795'
so it should -9 or -8 here? please help me understand about the dates and what dates will be included here ?
If my Tuesday is 15th Oct and the previous Sat is 12thoct and mon is 7thoct
I need data from Mon7th oct to sat12th oct
if you want to get data from Monday to Saturday. WeekDay is from 2(Monday) to 7(Saturday)
select *
from VP_TIMESHTPUNCHV42
where datepart(weekday, EVENTDATE) between 2 and 7 AND PERSONNUM = '668795'
or (if only within this week)
select *
from VP_TIMESHTPUNCHV42
where EVENTDATE between getdate() - 1 and getdate() + 5 AND PERSONNUM = '668795'
select *
from VP_TIMESHTPUNCHV42
where EVENTDATE between dateadd(day, -1, cast(getdate() as date)) and dateadd(day, 5, cast(getdate() as date))
and PERSONNUM = '668795'

Getting all data ranges which contains a flagged day of the week in a given interval

I Have a table which contains information about blockages in a operation for every day of the week in date range. Given that, I need to perform a query which brings only the records that have an active blockage in a given range. E.g.: Suppose there are three registers in the table.
START_DATE END_DATE MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY
2019-01-01 2020-12-31 1 0 0 0 0 0 0
2019-01-31 2019-02-03 0 0 0 0 0 0 1
2018-01-01 2100-12-31 0 0 0 0 0 1 1
And I want to get all the registers which have a blockage between 2019-01-31 and 2019-02-02 (Thursday, Friday and Saturday). The result should bring only the last register.
Is there any way of performing this search entirely in the data base using SQL?
At first, you will have to find intersections of the intervals in the table and the interval you are interested in. Assuming that you define the criteria using two variables #StartDate and #EndDate, it could look like this:
WHERE START_DATE <= #EndDate AND END_DATE >= #StartDate
Then, you will have to find the start and end of the intersection interval:
CASE WHEN START_DATE > #StartDate THEN START_DATE ELSE #StartDate END
CASE WHEN END_DATE < #EndDate THEN END_DATE ELSE #EndDate END
To decide, for example, if that interval contains a Saturday, I count the number of complete weeks between an initial Sunday and the start date and compare that to the respective number for the day after the end date. If both numbers differ, the interval contains a Saturday. My complete suggestion looks like this:
DECLARE #StartDate date = '20190131', #EndDate date = '20190202';
SELECT YourTable.* FROM YourTable
CROSS APPLY( VALUES (
CASE WHEN START_DATE > #StartDate THEN START_DATE ELSE #StartDate END,
CASE WHEN END_DATE < #EndDate THEN END_DATE ELSE #EndDate END)
) Intersection (iStart, iEnd)
CROSS APPLY(
VALUES(DATEDIFF(day, 0, iStart), 1 + DATEDIFF(day, 0, iEnd))
) DaysCount (s, e)
WHERE START_DATE <= #EndDate AND END_DATE >= #StartDate
AND (
(e/7 > s/7 AND SUNDAY = 1)
OR ((e+1)/7 > (s+1)/7 AND SATURDAY = 1)
OR ((e+2)/7 > (s+2)/7 AND FRIDAY = 1)
OR ((e+3)/7 > (s+3)/7 AND THURSDAY = 1)
OR ((e+4)/7 > (s+4)/7 AND WEDNESDAY = 1)
OR ((e+5)/7 > (s+5)/7 AND TUESDAY = 1)
OR ((e+6)/7 > (s+6)/7 AND MONDAY = 1)
);
Remark:
For the counting of days, I use the initial “date 0”, which is 1900-01-01 (a Monday) in SQL Server.
You need to generate all the days and then look for any blockages by day of week:
with days as (
select convert(date, '2019-01-31') as dte
union all
select dateadd(day, 1, dte)
from dte
where dte < '2019-02-02'
)
select
from blockages b cross join
days d
where d.dte >= b.start_date and d.dte <= b.end_date and
( (datename(weekday, d.date) = 'Monday' and Monday = 1) or
(datename(weekday, d.date) = 'Tuesday' and Tuesday = 1) or
(datename(weekday, d.date) = 'Wednesday' and Wednesday = 1) or
(datename(weekday, d.date) = 'Thursday' and Thursday = 1) or
(datename(weekday, d.date) = 'Friday' and Friday = 1) or
(datename(weekday, d.date) = 'Saturday' and Saturday = 1) or
(datename(weekday, d.date) = 'Sunday' and Sunday = 1)
);
Note that if you have more than 99 days in your range, you'll need to include option (maxrecursion 0) to generate the days. Alternatively, you can use a calendar table or tally table.

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

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

week beginning (Monday) for previous day

I want to pull all the data for the week to the previous day.
for example:
if the date was Monday 2016-05-09. I would like the previous Monday 2016-05-02 to Sunday 2016-05-08.
If the date was Tuesday 2016-05-10. I would like the previous Monday 2016-05-09 to Monday 2016-05-09.
I have tried using with no joy.
and (ShiftDate Between DATEADD(wk, 0, DATEADD(DAY, (1-DATEPART(WEEKDAY, GETDATE()-1)), DATEDIFF(dd, 0, GETDATE())))and GETDATE()-1)
You should use this:
and (ShiftDate Between (GETDATE() - 1 - (DATEPART(weekday, GETDATE() -1) + 7 - 2) % 7)
and (GETDATE()-1)
)
Because Sunday is 1 in weekday so you should add 7 then module by 7 to get the different from nearest Monday (2 in weekday) to the previous day.