How to pull week to date data in SQL Server? - sql

I'm trying to pull week to date data for a recurring report that needs to go out daily. For eg: report that goes out Monday needs to have data for Monday, report that goes out Tuesday will have data for Monday and Tuesday etc. for the current week.
I know how to pull last X days data with :
my_date > DATEADD(day, -6, GETDATE())
How do I pull only week to date?

Use below SQL code in where condition:
where
my_date > DATEADD(dd, -((DATEPART(WEEKDAY, mydate) + 5) % 7), DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0))

The correct adjustment requires a bit of extra modular arithmetic and so the proper number of days to adjust backward works out to the expression below. I am also assuming that datefirst is set to Sunday:
-((DATEPART(WEEKDAY, mydate) + 5) % 7)
If you just subtract two from the day number given by datepart() then you'll end up with a negative number on Sundays which then cause dateadd() to jump forward. You can see a listing of dates and comparison here:
https://rextester.com/IUY88999

Related

Pull data from the third week back from this week? [duplicate]

This question already has answers here:
Query to get content older than 3 weeks
(3 answers)
Closed 2 years ago.
This week is the week of 12/28/20. I want to pull data from the third week back of whatever the current week is. So if I run my query today I want it to pull data for the week of 12/7 only. I'm trying to do this and its not returning any results. Any ideas? Thank you
WHERE date = DATEADD(week, -3, GETDATE())
I prefer the following which:
Allows you to use the Date column without calling a function on it. This is important for sargability i.e. the ability for SQL Server to use an index on the Date column. Although in my testing a cast to date still did you use the index, its best practice to avoid functions calls on the columns in where clauses.
Avoids the use of between, which I always have to take a moment to think about because its >= the first condition and <= the second condition. So its easy to get the logic wrong and include 8 days instead of 7. Instead I always use an explicit compare so its obvious what the logic is.
Note the >= and < now rather than <=.
where [Date] >= convert(date,dateadd(week, -3, current_timestamp))
and [Date] < convert(date,dateadd(week, -2, current_timestamp))
Now
Start Of Week (Inc)
End Of Week (Ex)
2020-12-29 20:07:16.373
2020-12-08
2020-12-15
And if you need it to start on your week start day then use:
where [Date] >= convert(date,dateadd(day, (-1*datepart(weekday,current_timestamp))+1, dateadd(week, -3, current_timestamp)))
and [Date] < convert(date,dateadd(day, (-1*datepart(weekday,current_timestamp))+1, dateadd(week, -2, current_timestamp)))
Now
Start Of Week (Inc)
End Of Week (Ex)
2020-12-29 20:07:16.373
2020-12-06
2020-12-13
That is only going to give you data that has a date that was three weeks ago from the current time to the nearest thousandth of a second. It's fairly unlikely that you have any data that exactly matches that.
What I expect you are after is data that is between three and two weeks ago which can be obtained like this:
WHERE date BETWEEN DATEADD(week, -3, GETDATE()) AND DATEADD(week, -2, GETDATE())
However if you run that half way through a day, it will only give you data from half way through the day three weeks ago until half way through the day two weeks ago. You probably want to go from midnight at the start and end of the day. This can be done by casting everything to the DATE type, which has the effect of discarding the time, like this:
WHERE CAST(date AS DATE) >= CAST(DATEADD(week, -3, GETDATE()) AS DATE) AND CAST(date AS DATE) < CAST(DATEADD(week, -2, GETDATE()) AS DATE)
It is also possible that you want to have the weeks always start on the same day of the week. This can be done using the DATEPART function.
WHERE DATEPART(week, date) = DATEPART(week, DATEADD(week, -3, GETDATE())) AND DATEPART(year, date) = DATEPART(year, DATEADD(week, -3, GETDATE()))
Depending upon what you want and how your database is set up this last option may require setting the SET DATEFIRST setting to get the correct day to start the week on. For example to start the week on Mondays use:
SET DATEFIRST 1;

Data Preparation End OF Every Month - Moving Over 12 Months

I have data prep procedure in SQL. I want to have data preparation at the end of every month
Say I want the procedure run on last day of month e.g. on 31 January 2020 it should prep data from 1 January to 31 January.
So it's kind of moving window over all months of the year. Because I need data for evaluation at the end of each month.
I tried this, however, this does not give automation. Its sort of manual running end of every month
select '2020-10-01' as beginDate_AnalysisWindow
, '2020 -01-31' as endDate_AnalysisWindow
into #AnalysisWindow --create temporary table #AnalysisWindow
I also tried the following, however, I’m not sure if it does for the whole month or just one day?
SELECT START_OF_MONTH_DATE AS beginDate_AnalysisWindow
,END_OF_MONTH_DATE AS endDate_AnalysisWindow
INTO #AnalysisWindow
FROM [dbo].[Date] WITH (NOLOCK)
WHERE DATE = DATEADD(dd, - 1, CAST(GETDATE() AS DATE))
Could someone pls help me/give me some suggestions.
Thanks in advance
If you want the last day of the current month, use eomonth():
WHERE DATE = CONVERT(date, EOMONTH(GETDATE()))
Note: This assumes that the date column has no time component. If that is the case:
WHERE CONVERT(date, DATE) = CONVERT(date, EOMONTH(GETDATE()))
SQL Server will still use an index (if available) even for this type of conversion.
EDIT:
To get the current months data, one method is:
WHERE DATE <= CONVERT(date, EOMONTH(GETDATE())) AND
DATE > CONVERT(date, EOMONTH(GETDATE(), -1))
The second argument to EOMONTH() is a months offset.
You can also try:
where getdate() <= EOMONTH(GETDATE()) AND
getdate() > DATEADD(DAY, 1, EOMONTH(GETDATE(), -1))
Instead of getdate(), you can use your date column.

How to Target Last Month in SQL Query

I'm using this code in an SQL query
WHERE [Date] >= DATEFROMPARTS(DATEPART(year,GETDATE()),DATEPART(month,GETDATE())-1,DATEPART(day,GETDATE()))
AND [Date] <= EOMONTH(DATEFROMPARTS(DATEPART(year,GETDATE()),DATEPART(month,GETDATE())-1,DATEPART(day,GETDATE())));
The problem is come 2020 the December query will through up an error
The code I posted manages the dates between which data will be returned. It looks at the date the code is run and choose that day from last month till the end of last month. What I need is dates from the 1st till the last day of the month prior to the one this code is called in.
I will be working on this issue tomorrow, it will be interesting to see what solutions other people can come up with.
try this
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0),
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) - 1
it will get you the previous month start and end date
If you want the previous month:
where date >= dateadd(month, -1, datefromparts(year(getdate(), month(getdate(), 1))) and
date < datefromparts(year(getdate(), month(getdate(), 1))
This simply checks that it is before the first of the this month and then subtracts a month from that.

SQL 'Round' Up a Date to a Given Day of the week

My company groups all tasks into individual weeks that end on a Thursday. Thus a task due on 3/20/19 would be grouped into the 3/21 week and tasks due on 3/22 group into the 3/28/19 week.
I'm looking to calculate this field (called duedate_Weekdue) based on an input duedate.
The following works but doesn't seem like the simplest way to do this. Anyone have more elegant methods?
Select
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
CASE
When datename(dw,Dateadd(day,1,getdate()))='Thursday' Then Dateadd(day,1,getdate())
When datename(dw,Dateadd(day,2,getdate()))='Thursday' Then Dateadd(day,2,getdate())
When datename(dw,Dateadd(day,3,getdate()))='Thursday' Then Dateadd(day,3,getdate())
When datename(dw,Dateadd(day,4,getdate()))='Thursday' Then Dateadd(day,4,getdate())
When datename(dw,Dateadd(day,5,getdate()))='Thursday' Then Dateadd(day,5,getdate())
When datename(dw,Dateadd(day,6,getdate()))='Thursday' Then Dateadd(day,6,getdate())
When datename(dw,Dateadd(day,0,getdate()))='Thursday' Then Dateadd(day,0,getdate())
END as duedate_Weekdue;
You can reduce that to one line of code that uses a little math, and some SQL Engine trivia.
The answers that depend on DATEPART return non-deterministic results, depending on the setting for DATEFIRST, which tells the SQL Engine what day of the week to treat as the first day of the week.
There's a way to do what you want without the risk of getting the wrong result based on a change to the DATEFIRST setting.
Inside SQL Server, day number 0 is January 1, 1900, which happens to have been a Monday. We've all used this little trick to strip the time off of GETDATE() by calculating the number of days since day 0 then adding that number to day 0 to get today's date at midnight:
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()),0)
Similarly, day number 3 was January 4, 1900. That's relevant because that day was a Thursday. Applying a little math to the number of days, and relying on the DATEDIFF function to drop fractions, which it does, this calculation will always return the next Thursday for you:
SELECT DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3);
Credit to this answer for the assist.
So your final query comes down to this:
Select
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3) as duedate_Weekdue;
If the first day of the week is Sunday, by using the modulo operator %:
cast(dateadd(day, (13 - datepart(dw, getdate())) % 7, getdate()) as date) as duedate_Weekdue
I also applied the casting of the result to date.
Try identifying number of day in week with DATEPART and then adding enough days to go to next thursday:
declare #dt date = '2019-03-22'
declare #weekDay int
SELECT #weekDay = DATEPART(dw, #dt)
if #weekDay <= 5
select DATEADD(day, 5 - #weekDay ,#dt)
else
select DATEADD(day, 12 - #weekDay ,#dt)

How to write a query that selects last specific day and goes back 1 week from there?

I use this query on SEDE. I have just been editing the WHERE p.CreationDate > '2014-12-21T00:00:00.001' like every week to select the last week's records only. So for example previous edits were just changing to 12-21 from 12-14 from 12-7, etc..
I'm trying to edit that part so that I don't have to keep editing it every week.
I was thinking I could do something like
WHERE DATEDIFF(DAY, p.creationDate, GETDATE()) <= 7
which would select only results from the last 7 days.
However, this will only work on like Sunday when SEDE is updated. If I run a query on Wednesday, then this query will be missing three days of results.
How could I write this where statement to like find the last nearest Sunday, or is Sunday, and then go back one week from there?
To find previous sunday use this piece of code.
select DateAdd(dd, -1, DateAdd(wk, DateDiff(wk, 0, getdate()), 0)) [Previous Sunday]
Where clause should be something like.
Select ... from tablename
WHERE DATEDIFF(DAY, p.creationDate, DateAdd(dd, -1, DateAdd(wk, DateDiff(wk, 0, getdate()), 0))) <= 7
There are several solutions, similar to this.
Replace the GetDate in your where clause with some thing like
Cast(DateAdd(day,-DatePart(weekday,GetDate())+1,GetDate()) as Date)
where the +1 is adjusted larger or smaller to move to the specific day of the week you want to start with. The +1 causes this to becaome sunday.
-- Assuming your db ##DATEFIRST in on sunday (i.e 7)
WHERE p.creationdate >= DATEADD( day, -6 - DATEPART(weekday,GETDATE()), GETDATE() )