Dynamic Date Range in SSRS or SQL Data Tools builder - sql-server

I am making a report that will run on the 1st of every month and on the 16th of every month.
If it is running on the 1st I need the #start_date to be the 16th to the last day of the previous month.
If it is running on the 16th I need #start_date to be the 1st of the month through the 15th of the month.
I can think of a couple ways to do this, but I am curious is SSRS/Report Builder/SQL Data Tools builder has an easy method for setting this up.
My option was to make a SQL query that does what I need then plug that into the Get Balues from a query part of the parameter.

If you run the report in the first part of the month then the parameters should be set to the 16th to the end of the previous month; if run in the second part of the month then the parameters should be set to the 1st to the 15th of the current month.
#start_date Default Value expression:
=IIF(Day(Today) >= 16, DateAdd(DateInterval.Day, 1-Day(Today), Today), DateAdd(DateInterval.Month, -1, (DateAdd(DateInterval.Day, 16-Day(Today), Today))))
#end_date Default Value expression:
=IIF(Day(Today) >= 16, DateAdd(DateInterval.Day, 15-Day(Today), Today), DateAdd(DateInterval.Day, -1, (DateAdd(DateInterval.Day, 1-Day(Today), Today))))

Related

Set report date for date other than today in SQL reporting

I have a report that I have been asked to produce. The first column of data is total time entered from the first of the year to the end of the previous month. The next column of data is total time from beginning of "current" month to the end of "current" month.
For example. If this report was being run for March then the first column would be total time for Jan and Feb and the second column would be total time for March. If I were to run it in April then the first column would be total time for Jan/Feb/Mar and the second column total time for April etc.
I am using various expressions to get first date of the year, last date of previous month, first date of this month, last date of this month. All working fine and it runs like a dream if you run the report in the current month (i.e. March) but if you want to run the report in April for March's data it won't do it as it's reading the date on the computer and using that to calculate the prev month.
In Crystal reports you can set a report date. Is there something similar in SQL reporting? I'm assuming you DECLARE the report date in your initial query but I haven't yet found the right combination of functions.
This report is for an external bit of software that we run.
The only parameters I can use are #FromDate and #ToDate and these are set as text rather than date
I was planning on using the #ToDate to set the report date but would obviously have to convert it from text first
Any guidance very much appreciated
Try this. You could actually do it without all the declare statements, I just did those to break it down to be easy to read.
declare #date_entered datetime = '2/7/2017'
declare #start_of_year datetime = DATEADD(yy, DATEDIFF(yy, 0, #date_entered), 0)
declare #start_of_month datetime = DATEADD(month, DATEDIFF(month, 0, #date_entered), 0)
declare #end_of_month datetime = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#date_entered)+1,0))
declare #end_of_last_month datetime = DATEADD(day,-1,#start_of_month)
-- Now remove weekends from days found
declare #amount_of_days_previous tinyint = datediff(day,#start_of_year,#end_of_last_month) - (datediff(wk, #start_of_year, #end_of_last_month) * 2)
declare #amount_of_days_this tinyint = DATEDIFF(day,#start_of_month,#end_of_month) - (datediff(wk, #start_of_month, #end_of_month) * 2)
select #amount_of_days_previous * 8 as WorkHoursinDaysPrevious,
#amount_of_days_this * 8 as WorkHoursinDaysThis
I had a think over the weekend and realised that I was approaching the problem all wrong. I was trying to set the report date so that my query could read that date and then go back and find the relevant date (first date in the year, last date of previous month etc).
What I needed to do was use my date criteria (FromDate and ToDate) in my DATEADD selections.
CONVERT(datetime,#FromDate,103) AS FIRSTDAYOFYEAR,
DATEADD(D, - 1, DATEADD(MONTH, DATEDIFF(MONTH, '19000101', CONVERT(datetime,#ToDate,103)), '19000101')) AS LASTDAYPREVMONTH,
DATEADD(MONTH,DATEDIFF(MONTH, '19000101',CONVERT(datetime,#ToDate,103)), '19000101') AS FIRSTDAYMONTH,
CONVERT(datetime,#ToDate,103) AS LASTDAYMONTH,
This is now much better because my "first date of year" can be anything the user wants, not just the first day of the year.

Query all items for the week in SQL

I have a query that selects all items for the given week and sets their date to be the start day of that week. In some cases the query sets an incorrect date value for the given item and I have traced the problem to be in either DATEDIFF or DATEADD functions.
The query is
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, DateTimeValue), 0) AS NewDateTimeValue
Let's take a date March 27 2016 as an example. The DATEDIFF returns value of 6065 and the DATEADD with that value returns March 28 2016.
For the date March 26 2016, the DATEDIFF returns 6064 and the DATEADD March 21, 2016.
To me this sounds like a FirstDayOfWeek issue and that SQL Server thinks Sunday is the first day of a week and thus giving different values for Sunday and for Saturday (March 27, 2016 is Sunday).
I tried to set the first day of the week by
SET DATEFIRST 1
but that didn't make any difference and SQL returned the same results.
So what causes the SQL function to behave like this and any ideas how to fix it?
I found out that DATEDIFF doesn't respect the DATEFIRST setting and always assumes the week starts on Sunday. This is the reason why my sample case works as it works. This question has some suggested workaround: Is it possible to set start of week for T-SQL DATEDIFF function?
This is happening because you are finding the no. of weeks from date 0 to the supplied date. 0 is actually '1900-01-01' which was a Monday. Therefore,DATEDIFF finds the number of completed weeks from this date until the supplied data. Thats why DATEDIFF for March 27 2016 returns 6065 (as it is the end of a week) and March 26 2016 returns 6064 (as it is still not the end of a week).
This is already explained in this link - Get first day of the week

SQL Week of Month without DATEFIRST

I am working with dates so I have created a function that generates a SQL Table Calendar which returns Day, Month, WeekOfMonth, WeekOfYear and so on.
Right now, for the Day of Month field I am using the following function:
-- [WkNo]=Week number
[WkNo] = DATEPART(week,dt.DT),
But the problem is that when I run this on a SQL installed with Language = US English, the week setting is wrong cause the week starts from Sunday.
I need to set the week starting from Monday, is it possible without the use of DATEPART?
Update: based on asker's comment that he cannot use the DATEFIRST approach I am updating answer.
Note:
This answer is generic in nature.
If instead of Monday you want the week to start from Tuesday, you can change the dateadd(dd,-1,dt.DT) to dateadd(dd,-2,dt.DT) and for Wednesday to dateadd(dd,-3,dt.DT).
Basically the formula becomes dateadd(dd,-n,dt.DT) for value of n ranging over 1(Monday) to 6 (Saturday).
SELECT [WkNo]=
ISNULL(DATEPART(week,
case
when Year(dt.DT)>YEAR(dateadd(dd,-1,dt.DT))
then null
else dateadd(dd,-1,dt.DT)
end
),1)
See working fiddle http://sqlfiddle.com/#!6/10a80/14
Old Answer:
See MSDN documentation: https://msdn.microsoft.com/en-us/library/ms174420.aspx
When datepart is week (wk, ww) or weekday (dw), the return value
depends on the value that is set by using SET DATEFIRST. January 1 of
any year defines the starting number for the week datepart, for
example: DATEPART (wk, 'Jan 1, xxxx') = 1, where xxxx is any year.
SET DATEFIRST 1
-- [WkNo]=Week number
[WkNo] = DATEPART(week,dt.DT),
try
SET DATEFIRST {1,2,3,4,5,6,7(default, U.S. English)}
for your Query:
set datefirst 1
select [WkNo]= DATEPART(week,dt.DT)
See Here

How do I use dateadd to get the first day of last year?

I'm trying to pull data that falls in between January 1st, 2014 and today's date last year (ie. August 3rd, 2014). How would I go about using ``dateadd` to get the date 1/1/14? I'm using the following code to get the date 8/3/14.
dateadd (yy, -1, getdate())
I want to avoid explicitly searching for 1/1/14 because in a year's time I'd like the sql query to find 1/1/15 without me having to go back in and rewrite it.
Use DATEFROMPARTS:
DATEFROMPARTS(YEAR(GETDATE()) - 1, 1, 1)
DATEADD(yy, DATEDIFF(yy,0,getdate())-1, 0)
DATEFROMPARTS() is the best way but it requires SQL2012 or later. If you're on an earlier vierion, try this:
You can use GETDATE() to get the current date
You can use the function YEAR() to extract the year from any date
Subtract 1 from it to get last year
Append 1/1/ to the front of it
Convert it back to a date again
select convert(datetime, '1/1/' + convert(varchar(max),year(getdate())-1))

Use a report parameter instead of GETDATE in stored procedure

I have a SQL query which is saved as a stored procedure. I am using three different stored procedures to go back 1, 2, or 3 days depending on today's date. This makes it possible for my dashboard users to go back and skip weekends when comparing stats. This actually works. It looks at todays date and if it is Sunday go back 2 days, if it is Monday go back 3 days otherwise go back 1 day. The dashboard is created in Report Builder. Below is shown the between dates if today is Sunday (i.e. skip 2 days and go back to Friday which is the last normal working day). So much for the background. My challenge is now the user of the dashboard would like a BeginDate and EndDate date picker parameter in the report so I can no longer use these hard coded date strings but will have to incorporate a parameter into them. How do I replace a parameter say called #BeginDate in the following line where it says "GETDATE()":
BETWEEN DATEADD(DAY, -2, DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()), 0))
AND DATEADD(SECOND, -86401, DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()),0))
And based upon the date the end user selects then go and use one of the three stored procedures. I think I can make this work somehow, but I cannot figure out how to replace GETDATE() above with a parameter entered in by the user. If I just replace it with a parameter it throws back an error. I'm sure there is a really smart way of doing this. I'm still looking!!!
If you are passing a new parameter into the stored prcoedure:
BETWEEN DATEADD(DAY, -2, #BEGINDATE) AND DATEADD(SECOND, -86401, #BEGINDATE)
Adding seconds seems unnecessarily complicated:
>= DATEADD(DAY, -2, #BEGINDATE) and XXX < DATEADD(DAY, -1, #BEGINDATE)

Resources