Using Parameters to generate date range - sql-server

So I have multiple reports I am trying to merge into one report. The big issue is that one report is run every two weeks and the other is run once a month.
The date range for the report was created using this sql
SELECT
CASE
WHEN DAY(GETDATE()) <= 15 THEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) + 15
ELSE
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) , 0)
END AS LO_DATE
So I tried adding a parameter that I could use that would basically say, hey if this is checked, then always run it for the whole month not the last two weeks. That sql looks like this.
IF (#RUN_FOR_MONTH = 'true')
SELECT
CASE
WHEN DAY(GETDATE()) <= 15 THEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) + 15
ELSE
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) , 0)
END AS LO_DATE
ELSE
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) , 0) AS LO_DATE
However I keep getting this error:
The report parameter ‘LO_DATE’ has a DefaultValue or a ValidValue that depends on the report parameter “RUN_FOR_MONTH”. Forward dependencies are not valid.
I am new to using SQL Server Report Builder, so if you need more information, please ask and I'll provide it.
REQUESTED CHANGE - I still get the same error
SELECT
CASE
WHEN #RUN_FOR_MONTH = 'true' THEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) , 0)
WHEN DAY(GETDATE()) <= 15 THEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) + 15
ELSE
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) , 0)
END AS LO_DATE

Parameters in SSRS are derived sequentially. If you have a parameter that is based off another's value, you must list those parameters in in the correct sequential order. Take the below
In this example, #DateFrom would be evaluated first, and then #DateTo; thus #DateFrom cannot depend on #DateTo (however the reverse is fine).
If, for example, the value of #DateFrom was DateAdd("d", -2, #DateTo) you would receive the error you have above. You would need to select #DateTo and click the Up Arrow icon (Or select #DateFrom and the down arrow)

Related

Subtract 1 year and 1 day at SQL Server

In order to subtract 1 year I use
SELECT DATEADD(year, -1, GETDATE())
Likewise for the day.
What is the syntax if I want the combination??
ex from 30/05/2020 ---> 29/05/2019
Wrap that in another DATEADD call.
SELECT DATEADD(DAY, -1, DATEADD(YEAR, -1, GETDATE()))
You could do the following, as SQL Server adds/subtracts days by default:
SELECT DATEADD(year, -1, GETDATE()-1)

What is the difference between date handling in my queries?

I need the number of records of last month. I used to use this approach so far:
select
count(ID)
from
table
where
col1 = 'somerule'
and
DateTimeOfInsert >= '20150901'
and
DateTimeOfInsert <= '20150930'
Now I'm about to atomate this task and therefore I have to pull the start and end dates of last month automatically. So here it is:
select
count(ID)
from
table
where
col1 = 'somerule'
and
DATEPART(m, DateTimeOfInsert) = DATEPART(m, DATEADD(m, -1, getdate()))
and
DATEPART(yyyy, DateTimeOfInsert) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
My only issue is that at this very moment the first query returns 1073 and the second one 1124. So the question is obvious: what is the difference between them? Both should inlude the start and end date. I can't spot it.
This condition:
DateTimeOfInsert >= '20150901' and DateTimeOfInsert <= '20150930'
retrieves record that are between 2015-09-01 00:00:00.000 and 2015-09-30 00:00:00.000.
If DateTimeOfInsert is DATETIME, then this will return different result from your other condition.
The best way for this kind of queries is not to use BETWEEN but rather use
>= and <. In your case, you want to get records for the last month, so you want to use >= start of last month and < start of this month:
DateTimeOfInsert >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0) -- Beginning of previous month
AND DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) -- Beginning of this month
The above condition also makes your query sargable.
For some common date routines, see this article.
The difference is in time component of datetime.
This:
DateTimeOfInsert >= '20150901' and DateTimeOfInsert <= '20150930'
will not select date like 20150930 15:30.
But this:
DATEPART(m, DateTimeOfInsert) = DATEPART(m, DATEADD(m, -1, getdate()))
will select it because you are checking for months and year part only. That`s why the second select returns more rows.
Both queries will return the same if you just change the first statement so that it will consider time component of last day of month:
DateTimeOfInsert >= '20150901' and DateTimeOfInsert < '20151001'

Query to get the first day of the month not working with DATEADD

I've been writing queries to truncate the time from a given datetime for years now, based on answers like this one and this one (and many other places), that groups a couple functions like
SELECT DATEADD(day, 0, DATEDIFF(day, 0, getdate()))
and it always gives the right answer.
I figured I could translate the same logic to finding the first of the current month by using month instead of day, but it's giving me a weird date for the result: 1903-10-17, instead of 2015-05-01.
My parameters have always been in the wrong order.
It turns out the format for DATEADD I've been using all these years is wrong, and it's only been working because it's using the day datepart. Casting an int to a date increments the day:
SELECT CAST(0 AS datetime) = '1900-01-01 00:00:00.000'
SELECT CAST(1 AS datetime) = '1900-01-02 00:00:00.000'
SELECT CAST(2 AS datetime) = '1900-01-03 00:00:00.000'
I should be using DATEADD(d, DATEDIFF(d, 0, getdate()), 0) - the parameters are (datepart, number, date), as laid out here at MSDN.
Writing it as SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) gives the expected result of 2015-05-01.

Calculating Next Due Date

I'm new to T-SQL and have come upon a piece of code and was wondering if someone could help me understand what is happening. The point of the code is to calculate the date the next payment.
CASE
WHEN MONTH(table.field-10) < MONTH(GETDATE())
THEN CONVERT(DATE,((MONTH(GETDATE()) - MONTH(table.field-10)) *30) + (table.field))
WHEN MONTH(table.field-10) = MONTH(GETDATE())
THEN CONVERT(DATE,FA_NEXTDUE)
WHEN MONTH(table.field-10) > MONTH(GETDATE())
THEN CONVERT(DATE,(table.field) - ((MONTH(table.field-10) - MONTH(GETDATE())) *30))
END AS CurrentDueDate
This appears quite poorly written as it uses a "month" function that does not take the year into account. It appears to trying to determine if ten days before the date in "field" is in the same month as the current date. However, due to this not taking the year into account the output is a bit erratic.
A better way would be to use the datediff function.
CASE WHEN DATEDIFF(month, getdate(), (dateadd(day, -10, table.field))) < 0 then dateadd(month, DATEDIFF(month, getdate(), (dateadd(day, -10, table.field))), table.field)
CASE WHEN DATEDIFF(month, getdate(), (dateadd(day, -10, table.field))) = 0 then CONVERT(Date, fa_nextdue)
CASE WHEN DATEDIFF(month, getdate(), (dateadd(day, -10, table.field))) > 0 then dateadd(month, DATEDIFF(month, getdate(), (dateadd(day, -10, table.field))), table.field)
Even with this correction, I am skeptical that the output is what the business would require. You might want to dig into the requirements a little to see what exactly should be returned here.
FYI table.field-10 = ten days before the "field" date.

TSQL retrieve all records in current month/year

I have a datetime field called DateFinished. I need to be able to retrieve all records in which DateFinished is within the current month/year.
If you've only got a small number of rows, this will do to get all rows where DateFinished is in this month of this year.
SELECT *
FROM MyTable
WHERE Year(DateFinished) = Year(CURRENT_TIMESTAMP)
AND Month(DateFinished) = Month(CURRENT_TIMESTAMP)
This could get quite slow over a large number of rows though - in which case using DateAdd, DatePart and BETWEEN is probably more appropriate, and can take advantage of indexes (I don't have time to write an answer involving those right now!)
Just as an alternative - this should use an index on DateFinished.
SELECT *
FROM MyTable
WHERE DateFinished BETWEEN
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
AND
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0)
So the problem with #Bridge's method is use of index.
#Moose & #PCurd's method has a problems depending on how the data is stored.
#PCurd's method would work fine if all data collected on a day is rounded down to that day. E.g. event at 5pm is recorded as 2021-11-30 00:00:00. But if time is kept (which is assumed as it is a datetime field in Ops situation) then this data will be lost.
So you need to use the <> operators.
SELECT *
FROM MyTable
WHERE DateFinished >=
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
AND DateFinished <
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0)
For the method using datefromparts: SQL select records with current month

Resources