Decision based on what day of the week a date falls on - sql-server

For any given date I need to determine what day of the week it is.
I already know how to get the day of the week with this DATENAME(dw,MyDate.Field)and the number of the day with this DATEPART(dw,MyDate.Field).
Once I've got the day of the week if it is before Wednesday I want to return that Wednesday's date.
If the day of the week is Wednesday or after then I want to return next Wednesdays date.
Monday is day 1 in my system.

Use DATEPART() to determine day of the week.
Use CASE() for the different cases.
Calculate the day delta. Hint: It's either 3-dw or 7+3-dw.
Use DATEADD() to get from the current day (returned by DATEPART) to Wednesday or Wednesday of next week.

the easiest way, without any calculating:
set datefirst 1;
with dates as (
select CAST('20170906' as datetime) d
union all
select DATEADD(day, 1, dates.d)
from dates
where DATEADD(day, 1, dates.d) <= '20170930'
)
select dates.d, DATEADD(day, v.valueToAdd, dates.d) nextWed
from dates
join (values(1,2),(2,1),(3,7),(4,6),(5,5),(6,4),(7,3))v(dayOfWeek,valueToAdd) on v.dayOfWeek = DATEPART(weekday, dates.d)
order by 1

Related

How to do rolling weeks based on date?

I'm currently at a data analyst student job following an internship and I have do to reports based on the ticketing tool of the company, so, I'm using a pre-calculated table (the administrator have made pre-calculated tables based on his querys).
I have week table with all I need and I have to do a rolling 26 week report.
Because it is calculated that are historized and I don't have creation_date or end_date column.
I can't manage to do this can you help me with this ?
Actually, as a rolling query, if I have 18 weeks for 2021 I will need the 8 weeks last weeks of 2020.
I have this columns : Closed, Week, Month, Backlog... and I need it just for Closed.
I've tried this :
SELECT SUM(CLOSED), WEEK, MONTh, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE MONTH >= Month(getdate())-6
AND YEAR <= YEAR(getdate())
EDIT : The weeks range values 1 trough 53 or 52 it depends on the year, the weeks are weeks of month, I've tried this
SELECT SUM(CLOSED), WEEK, MONTH, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE
YEAR(DATEADD(WEEK, -26, GETDATE())) = YEAR(GETDATE()) - 1
AND
YEAR = YEAR(GETDATE())
AND
MONTH <= Month(DATEADD(WEEK, -26, GETDATE()))
)
group by WEEK, MONTH, YEAR
order by WEEK, YEAR
But I'm only getting week for the current year the previous year doesn't show.
I wonder if it's even possible to have the last year because without the pre-calculated tables I could get the last year with my querys but they want me to use this table.
Thank you for your help.
I don't see what your week value is but this will get you close:
SELECT SUM(CLOSED), WEEK, MONTH, YEAR
FROM E_GROUPE_INTERVENANT_SEMAINE_HISTORY
WHERE (--CURRENT YEAR WHEN YEAR IS NOT CROSSED
YEAR(DATEADD(WEEK, -18, GETDATE())) = YEAR(GETDATE())
AND
YEAR = YEAR(GETDATE())
AND
MONTH >= Month(DATEADD(WEEK, -18, GETDATE()))
)
OR
( --LAST MONTHS OF LAST YEAR WHEN YEAR IS SPANNED
MONTH >= Month(DATEADD(WEEK, -18, GETDATE()))
AND
YEAR = YEAR(DATEADD(WEEK, -18, GETDATE()))
)
OR
(--ALL MONTHS FOR CURRENT YEAR WHEN YEAR IS CROSSED
YEAR(DATEADD(WEEK, -18, GETDATE())) = YEAR(GETDATE()) - 1
AND
YEAR = YEAR(GETDATE())
AND
MONTH <= Month(DATEADD(WEEK, -18, GETDATE()))
)

SQL server week ending Thursday range

I'm trying to show the DateTimeRaised field as a week ending Thursday. The FkIssueGroupID isn't unique but each row should have the same date. The MAX is being used to bring back a single row.
Select distinct w.fkIssueGroupID
,[FormDateTimeRaised] =MAX ([DateTimeRaised])
,[WEnd Raised - Thur]= max (CONVERT (date, DATEADD(dd, 5 - (DATEPART(dw, [DateTimeRaised])), [DateTimeRaised]) ))
Whilst the week ending value for Thursday is correct the week days contained within it don't line up i.e.:
Week ending Thursday will have a date of the 21/05/20 (Thursday) but the date values covered by the data are 18/05 to 24/05 (Mon-Sun). I want the date range covered to be 15/05 to 21/05 (Fri-Thur). How do i get the date range to shift from Mon-Sun to Fri-Thur?
You can set the first day of the week to Friday like this:
SET DATEFIRST 5;

How to find the past 4 weeks of the same weekday value starting today

I am trying to select records from today and the same day of each week for the last 4 weeks.
Today (Tuesday)
Last Tuesday
The Tuesday before that
The Tuesday before that
I need this to be tied to current date because I am going to run this query every day so I don't want to use a between or something where I manually specify the date range.
Everything I have found or tried so far has pulled the last month of data but not the last 4 weeks of the same weekday.
select *
from table
where thedatecolumn >= DATEADD(mm, -1, GETDATE())
This works but pulls everything from the last month.
If today's date is 7/10/2019 I need
Data from 7/10/2019
Data from 7/3/2019
Data from 6/26/2019
Data from 6/19/2019
Every day I will run this query, so I need it to be dynamic based on the current date.
I believe you want to look back 21 days and then filter those dates that have the same day of week:
select * from table
where thedatecolumn >= DATEADD(DAY, -21, CAST(GETDATE() AS DATE))
and DATEPART(WEEKDAY, thedatecolumn) = DATEPART(WEEKDAY, GETDATE())
You Can try using a recursive cte which starts today and repeatedly substracts 7 days - so you ensure you always land on the same weekday. Following an example:
WITH cteFromToday AS(
SELECT 0 AS WeeksBack, GETDATE() AS MyDate
UNION ALL
SELECT WeeksBack + 1 AS WeeksBack, DATEADD(d, -7, MyDate) AS MyDate
FROM cteFromToday
)
SELECT TOP 5 *
FROM cteFromToday
OPTION ( MaxRecursion 0 );
This is quite simple. Substitute CURRENT_TIMESTAMP here for any given date.
SELECT CONVERT(DATE,CURRENT_TIMESTAMP) AS Today,
DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)) AS LastWeek ,
DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)) AS TwoWeeksAgo,
DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP)) AS ThreeWeeksAgo
SO, if you want to get data for a set of ranges for one entire day with those dates:
SELECT something
WHERE
datetimecolumn >= CONVERT(DATE,CURRENT_TIMESTAMP) AND datetimecolumn < DATEADD(DAY,1, CONVERT(DATE,CURRENT_TIMESTAMP)) -- Todays range,
OR datetimecolumn >= DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1,DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)))-- LastWeek ,
OR datetimecolumn >= DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1,DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)))-- TwoWeeksAgo,
OR datetimecolumn >= DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1, DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP))) -- ThreeWeeksAgo

Replicate SQL Server DATEPART(wk, ...) function in Delphi

Delphi's WeekOfTheYear function uses the ISO 8601 methodology where the week starts on a Monday, and the first week of a year is defined as the first week with four or more days in that year.
To get the week of the year in Microsoft SQL Server, you use the DATEPART(wk, ...) function, but this uses a different mechanism, in that the default for U.S. English starts the week on Sunday, and that the 2nd week of the year is the first Sunday of the year, unless that Sunday is the 1st of January, then the 2nd week starts on the 2nd Sunday of the year, as can be seen if you run this example:
SELECT '2010-1-3', DATEPART(wk, '2010-1-3'), DATENAME(dw, '2010-1-3')
SELECT '2011-1-2', DATEPART(wk, '2011-1-2'), DATENAME(dw, '2011-1-2')
SELECT '2012-1-1', DATEPART(wk, '2012-1-1'), DATENAME(dw, '2012-1-1')
SELECT '2013-1-6', DATEPART(wk, '2013-1-6'), DATENAME(dw, '2013-1-6')
SELECT '2014-1-5', DATEPART(wk, '2014-1-5'), DATENAME(dw, '2014-1-5')
SELECT '2015-1-4', DATEPART(wk, '2015-1-4'), DATENAME(dw, '2015-1-4')
SELECT '2016-1-3', DATEPART(wk, '2016-1-3'), DATENAME(dw, '2016-1-3')
SELECT '2017-1-1', DATEPART(wk, '2017-1-1'), DATENAME(dw, '2017-1-1')
SELECT '2018-1-7', DATEPART(wk, '2018-1-7'), DATENAME(dw, '2018-1-7')
SELECT '2019-1-6', DATEPART(wk, '2019-1-6'), DATENAME(dw, '2019-1-6')
SELECT '2020-1-5', DATEPART(wk, '2020-1-5'), DATENAME(dw, '2020-1-5')
The results from above show every Sunday being the 2nd week of the year, except for the 2 that are the 1st January, which show the 1st week of the year.
I looked at the answer for the question below, that seemed to indicate it would return the week of the year depending on what day the week starts,
Delphi week number function based on system start of week
but that is also based on using the Delphi functions, and does not return the same results as SQL Server.
What SQL Server currently shows for the dates 1st January 2018 to 8th January 2018 is:
1/1/2018 = 1
2/1/2018 = 1
3/1/2018 = 1
4/1/2018 = 1
5/1/2018 = 1
6/1/2018 = 1
7/1/2018 = 2
8/1/2018 = 2
Delphi does have a DayOfWeek function that uses Sunday as the first day of the week, compared to the DayofTheWeek function which uses Monday, but I just can't seem to work out the logic that is needed to get the same results as SQL Server. There has to at least be a condition in there for dealing with Sunday 1st January being week 1, but for the first other Sundays being week 2.
Does anyone have any Delphi source code that returns the week of the year exactly as SQL Server does when using U.S. English default of DATEFIRST 7?
The code is deceptively simple, but the logic of it is a little difficult. The rule about the first Sunday means that, in all cases the first Saturday is in week 1. So the idea is that we go to the next Saturday and count the number of Saturdays from the start of the year.
function SQLWeekOfYear(const pDate: TDate): integer;
var
iYear, iMonth, iDay : word;
iDOW : integer;
iDays : integer;
begin
// this is based on First Sunday in year being in week 2
// unless it is the first of Jan, which is equivalent of saying that the
// first saturday is always in week 1.
//
// This means that we count the number of saturdays prior to this date and add one,
// which is equivalent to finding the next saturday
DecodeDate( pDate, iYear, iMonth, iDay );
iDOW := DayOfWeek( pDate );
// Find how many days so far since 1st jan
iDays := Trunc(pDate - EncodeDate( iYear, 1, 1 )) + 1;
// now adjust for day of week to get to next saturday
iDays := iDays + (7-iDOW);
// add 6 and divide by 7 to find actual number saturdays
Result := (iDays + 6) div 7;
end;

MSSQL order by previous 7 days

I run this query in MSSQL to get the items, grouping by the last 7 days of the week:
SELECT COUNT(Date_Entered), DATENAME(WEEKDAY, Date_Entered)
FROM my_table
WHERE Board_Name = 'Board'
AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATENAME(WEEKDAY, Date_Entered)
In the result, days of the week are sorted in alphabetical order: Friday > Monday > Saturday > Sunday > Thursday > Tuesday > Wednesday
How do I sort by the normal/correct/common sense order, starting with the weekday of 7 days ago and ending with yesterday?
Ordering by MAX(Date_Entered) should work too:
SELECT
COUNT(Date_Entered),
DATENAME(WEEKDAY, Date_Entered)
FROM my_table
WHERE Board_Name = 'Board' AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATENAME(WEEKDAY, Date_Entered)
ORDER BY MAX(Date_Entered);
Normally you would want to order by the date ascending, but since you use an aggregate function you would need to group by the date which would ruin it, but since the max(date) in every group is the date you can do max(date) to order.
DATEPART is your friend, try it like this:
SELECT COUNT(Date_Entered), DATENAME(WEEKDAY, Date_Entered),DATEPART(WEEKDAY,Date_Entered)
FROM my_table
WHERE Board_Name = 'Board'
AND DATEDIFF(DAY,Date_Entered,GETDATE()) <= 7
GROUP BY DATEPART(WEEKDAY,Date_Entered),DATENAME(WEEKDAY, Date_Entered)
ORDER BY DATEPART(WEEKDAY,Date_Entered)
If you can't count on data being available for every week then you'd need to do something more based on date calculations. Off the top of my head I think this will be more reliable:
ORDER BY (DATEDIFF(dd, MAX(Date_Entered), CURRENT_TIMESTAMP) + 77777) % 7
EDIT: I wrote that not realizing that the data was already limited to a single week. I thought the intention was to group in buckets by day of week for a longer range of dates.
I'll also comment that to me it is more natural to do the grouping on cast(Date_Entered as date) rather than on a string value and I wouldn't be surprised if it's a more efficient query.

Resources