Values over a time period - sql

I would like to calculate a value in SQL that does the following:
if the user's inputted month parameter (I'm writing the SQL to aggregate information first then using SSRS) is 90 days or more past today (or the most recent data entry), then use the value for that month. Otherwise, if the month parameter is within 90 days of the report run date (or most recent data entry), use the most recent value that IS in fact 90 days past. For example, if I run the report in August and specify the month parameter as August, I will want the value from May. If I specify the month parameter as April, I want April's value since 90 days has gone by since then. Apologies if this isn't concise. I just would like some direction.
Cheers.

As suggested by #DanBracuk in the comments, you should probably take the parameter from SSRS and just update it based on the current date in your T-SQL code.
Say you have an SSRS parameter Parameters!Month.Value which gets passed to your stored procedure as #Month.
You can use GETDATE() and date functions like DATEDIFF() and DATEADD() to adjust #Month as required, e.g. in the stored procedure code something like:
select #Month = case when datediff(dd, #Month, getdate()) > 90
then #Month
else dateadd(dd, -90, #Month)
end
select *
from MyTable
where MyDate < #Month
Update the first statement to meet your requirements; they seem a bit ambiguous at this point - apologies if I haven't understood the issue completely.

Related

How to write a variable within SQL using Dateadd and DateDiff for finding the last TWO days of the previous month

I am trying to write a variable using the dateadd and datediff that shows the last two days of previous month. One variable will be the second to last day of the previous month, the one I am having trouble with. The other will be the last day of the previous month, the one I was able to get. I am using SQL Server.
I've tried looking for it on Stack and I have only seen the last day of the previous month given and NOT the second to last day. I tried learning the dateadd and datediff, (which I still want to do).
This is what I tried so far:
Declare #CurrentMonth as date = '3/1/2019'
Declare #SecLastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -2)
Declare #LastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -1)
The results I am getting for the seclastdayPrevMonth is 2/28/2019. Instead I would want 2/27/2019
I am also getting 2/28/2019 for lastdayprevmonth which is what I want.
I am writing variables because the current month will change every month, and instead of having to update the other days I need within my query, I want to use variables so I am only updating the current month and everything else is flowing through.
And explanation as to why my dateadd/datediff is wrong and an explanation for why the correct dateadd/datediff is the way it is, will be very helpful
Why not refer to the last day when calculating the second last day? Also, your usage of DATEADD is very weird. The syntax is DATEADD(interval, increment, datetime)
Declare #recmonth as date = '3/1/2019'
Declare #LastDayPrevMonth as date = EOMONTH(DATEADD(MONTH, -1, #RecMonth))
Declare #SecLastDayPrevMonth as date = DATEADD(DAY, -1, #LastDayPrevMonth)
SELECT #SecLastDayPrevMonth, #LastDayPrevMonth
So we can calculate the last day of the previous month by subtracting one month from a date and then calling EOMONTH, which returns the last day of a given month. Then the second last day is just subtracting one day from that.
Yields:
SecLastDayPrevMonth LastDayPrevMonth
------------------- ----------------
2019-02-27 2019-02-28
As to "why", DATEDIFF() takes 3 arguments: datepart (string representation of a specific date part), startdate, enddate (both of which must be convertible to a date-ish object).
0 is essentially SQL's epoch, which, in this case is 1/1/1900. So the difference in months between 0 and 3/1/2019 is (119*12)+2 (+2 because we exclude March, since we aren't calculating a full month) = 1430 months difference.
Then, we are trying to add 2 months to our value. DATEADD() takes 3 arguments: datepart, number, date. But, in the example, you are adding 1430 months to whatever date -2 gets converted to (in this case, I believe it would be 12/30/1899, or 2 days before epoch). So, 1430 months after 12/30/1899 would be 2/30/2019, but February only has 28 days in 2019, so it returns 2/28/2019. In a Leap Year, it probably would return 2/29/2019.
To get your #LastDayPrevMonth and #SecLastDayPrevMonth with only DATEDIFF() and DATEADD(), you just need to change your calculations a little.
First thing you want to do is find the First Day of your Given Month. That can be done with DATEADD(month,DATEDIFF(month,0,#CurrentDate),0). We're essentially using the same thing we used above to calculate the number of months since epoch, but then we are adding those months back to epoch.
Now that we know the First Day of the Given Month, all we have to do is subtract days to get a day from the prior month.
So,
DECLARE #CurrentDate date = '2019-03-15' ; -- Changed it to something in the middle of the month.
DECLARE #FirstDayOfGivenMonth = DATEADD(month,DATEDIFF(month,0,#CurrentDate),0) ; -- 3/1/2019
DECLARE #LastDayOfPrevMonth date = DATEADD(day,-1,#FirstDayOfThisMonth) ; -- 2/28/2019
DECLARE #SecLastDayOfPrevMonth date = DATEADD(day, -2, #FirstDayOfThisMonth) ; -- 2/27/2019
SELECT #LastDayOfPrevMonth AS LDPM, #SecLastDayOfPrevMonth AS SLDPM ;
DECLARE #FourDaysLeftInPrevMonth date = DATEADD(day, -4, #FirstDayOfThisMonth) ; -- 2/25/2019
SELECT #FourDaysLeftInPrevMonth AS FourDaysLeftPrev ;
Granted, since SQL 2012, this can all be accomplished much easier with the EOM() function to get to the last day of a month. But if you only could use the two original functions from your original question, this would be one way to get to your needed values.

WHERE statement to choose record previous day but choose Friday record when current day is Monday Microsoft SQL

I need a WHERE statement where the date of the record is the previous day. I have the below code which will do this
WHERE DOC_DATE = dateadd(day,datediff(day,1,GETDATE()),0)
However I need this statement to get Friday's record when the current day is Monday. I have the below code but it will not work for me. No errors come back on SQL although no records results come back either. I have the below code for this
WHERE DOC_DATE = DATEADD(day, CASE WHEN datepart(dw,(GETDATE())) IN (2) then -3 ELSE -1 END ,0)
Important to add that this needs to be in a WHERE clause. This is for a Docuware administrative view I am creating. I have no control on how to write the SELECT statement, I only have access to edit the WHERE clause:
Here's a slightly "magical" way to compute the value that doesn't depend on any particular server settings such as datefirst. It's probably not immediately obvious how it works:
WHERE DOC_DATE = dateadd(day,datediff(day,'20150316',getdate()),
CASE WHEN DATEPART(weekday,getdate()) = DATEPART(weekday,'20150330')
THEN '20150313'
ELSE '20150315' END)
In the first line, we're computing the number of days which have elapsed since some arbitrary date. I picked a day in March 2015 to use as my base date.
The second line asks what today's day of the week is and if it's the same as some arbitrary "Known good" Monday. Just taking one value and comparing it to 2 depends on what your DATEFIRST setting is so I prefer not to write that.
In the third line, we decide what to do if it's a monday - I give a date that is 3 days before my arbitrary date above. If it wasn't a monday, we pick the day before.
Adding it all together, when we add the days difference from the arbitrary date back to one of these two dates from lines 3 and 4, it has the effect of shifting the date backwards 1 or 3 days.
It's can be an odd structure to see if you're not familiar with it - but combining dateadd/datediff and exploiting relationships between an arbitrary date and other dates computed from it can be useful for performing all kinds of calculations. A similar structure can be used for computing e.g. the last day of the month 15 months ago using just dateadd/datediff, an arbitrary date and another date with the right offset from the first:
SELECT DATEADD(month,DATEDIFF(month,'20010101',GETDATE()),'19991031')
As I said in a comment though, usually doing this sort of thing is only a short step away from needing to properly model your organisation's business days, at which point you'd typically want to introduce a calendar table. At one row per day, 20 years worth of pre-calculated calendar (adjusted as necessary as the business changes) is still less than 10000 rows.
You can try this.
WHERE DOC_DATE = DATEADD(DAY, CASE WHEN datepart(dw, GETDATE()) = 2 THEN -3 ELSE -1 END, CAST(GETDATE() AS DATE))

Report that updates yearly

I have created a report that is supposed to look at the number of baptisms at our church for the ministry year. The Ministry year runs from Aug 1 - July 31. I currently have the report set to tell me the names of anyone that has a baptism date greater than 8/1/2016. But I would need to change that year each year for it to report properly. so I wanted to use a Case statement to have it update each year, but i am getting an error message with this: (The error is in the where clause, so I didn't include the entire report)
WHERE (P.organization_id = 1) AND
((CandidateProcesses_BaptismDate68.datetime_value) between (
case
When datepart(month, getdate()) < 8 then ('8/1/'+ datepart(year, getdate()))
When datepart(month, getdate()) >7 then ('8/1/'+
datepart((year,getdate())-1))End) and Getdate())
Does anyone see why I am getting an error?
Thanks!
You are getting an error trying to add a string and a number. You could fix that using datename() rather than datepart(). But, I think this is a simpler approach:
WHERE (P.organization_id = 1) AND
year(dateadd(month, -7, CandidateProcesses_BaptismDate68.datetime_value)) = year(dateadd(month, -7, getdate()))
This subtract 7 months to get the "ministry year" and then compares that to the current date minus seven months. That is, it subtracts 7 months and then normalizes on the calendar year.
This is a bit more expensive than your version, because it cannot use an index on CandidateProcesses_BaptismDate68(datetime_value). However, I doubt the database of baptisms is so large that the query will take very long anyway. (If that is an issue, then your version can be made to work with some simple modifications.)

Get the month and year now then count the number of rows that are older then 12 months in SQL/Classic ASP

I know this one is pretty easy but I've always had a nightmare when it comes to comparing dates in SQL please can someone help me out with this, thanks.
I need to get the month and year of now then compare it to a date stored in a DB.
Time Format in the DB:
2015-08-17 11:10:14.000
I need to compare the month and year with now and if its > 12 months old I will increment a count. I just need the number of rows where this argument is true.
I assume you have a datetime field.
You can use the DATEDIFF function, which takes the kind of "crossed boundaries", the start date and the end date.
Your boundary is the month because you are only interested in year and month, not days, so you can use the month macro.
Your start time is the value stored in the table's row.
Your end time is now. You can get system time selecting SYSDATETIME function.
So, assuming your table is called mtable and the datetime object is stored in its date field, you simply have to query:
SELECT COUNT(*) FROM mtable where DATEDIFF(month, mtable.date, (SELECT SYSDATETIME())) > 12

SQL - Determine last day of previous week with flexibility

I'm trying to create a flexible way to determine the last day of the previous week, knowing that this will be run in different environments that have different planning weeks (some customers use Sat-fri; Sun-Sat; Mon-Sun). I was planning on creating a variable to use as each customer's start day of the week (see below)
Set #BeginningWeek = 1 -- 1=Mon; 2=Tues; 3=Wed; 4=Thurs; 5=Fri; 6=Sat; 7=Sun
I've been trying to use a combination of dateadd and datepart, along with the variable above to try to get the previous last day of the week, but I'm having trouble with the logic. I do not want to use Set DateFirst, these scripts will be run on a customer environment, so I do not want to change anything in their DB.
Assuming the script is run on a wednesday (9/3); and the customer's planning week is sat-fri; I would want to set another variable #EndDate = the previous friday(8/29). I need the flexibility to use the same script (changing only the #BeginningWeek value) with another customer whose planning week is Mon-Sun and set #EndDate = the previous sunday (8/31).
This will get you the previous Saturday.
SELECT DATEADD(day,
-1 - (DATEPART(dw, GETDATE()) + ##DATEFIRST - 2) % 6,
GETDATE()
)
You should be able to replace the %6 bit with a parameter based on what the actual desired day is.