I have an SSIS for loop and in the assign expression part of the for loop I need to increment with a DATEADD function but the date part needs to be dependent on my variable:
#DateStart = DATEADD(#TypeIncrement,#DayIncrement,#DateStart)
If i change it ,it will work:
#DateStart = DATEADD(dd,#Increment,#DateStart)
but if I try to do it this way its just giving me an error saying The date part parameter specified for function "DATEADD" is not valid.
I have also tried changing it to be a case statement with different date parts but that wouldn't work either.
Any ideas?
Thanks.
----------------EDIT
a lot of ppl are posting sql server answers. but i need it working here:
Example
Declare #TypeIncrement varchar(10) = 'MM'
Declare #DayIncrement int = 5
Declare #DateStart date = '2017-03-15'
Select Case #TypeIncrement
When 'YY' then DateAdd(YY, #DayIncrement, #DateStart)
When 'QQ' then DateAdd(QQ, #DayIncrement, #DateStart)
When 'MM' then DateAdd(MM, #DayIncrement, #DateStart)
When 'WK' then DateAdd(WK, #DayIncrement, #DateStart)
When 'DD' then DateAdd(DD, #DayIncrement, #DateStart)
End
Returns
2017-08-15
The first parameter doesn't accept a variable as an input. One alternate option to a CASE might be dynamic SQL:
DECLARE #IncrementType nvarchar(10), #Increment int, #DateStart date;
SET #IncrementType = N'DAY';
SET #Increment = 5;
SET #DateStart = GETDATE();
IF #IncrementType NOT IN (N'YEAR',N'QUARTER',N'MONTH',N'DAYOFYEAR',N'DAY',N'WEEK',N'WEEKDAY',N'HOUR',N'MINUTE',N'SECOND',N'MILLISECOND',N'MICROSECOND',N'NANOSECOND') BEGIN
DECLARE #Error nvarchar(500) = 'Invalid input for Increment Type(''' + #IncrementType + N'''. Valid options are: YEAR, QUARTER, MONTH, DAYOFYEAR, DAY, WEEK, WEEKDAY, HOUR, MINUTE, SECOND, MILLISECOND, MICROSECOND, NANOSECOND.'
RAISERROR(#Error,11,-1);
END ELSE BEGIN
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'SET #dDateStart = DATEADD(' + #IncrementType + N',#dIncrement,#dDateStart)'
PRINT #SQL; --Your best friend
EXEC sp_executesql #SQL, N'#dDateStart date OUTPUT, #dIncrement int', #dDateStart = #DateStart OUTPUT, #dIncrement = #Increment;
END
SELECT #DateStart;
This might be over complicating it, but it's an alternate to the CASE anyway.
implementing inside SSIS:
to get this:
#DateStart = DATEADD(dd,#Increment,#DateStart)
Try this:
#DateStart = #TypeIncrement=="dd" ? DATEADD(dd,#Increment,#DateStart)
: #TypeIncrement=="mm" ? DATEADD(MM,#Increment,#DateStart)
and so on...
If then else is in the format of:
Test ? true part : false part
Related
I'm not sure if I get this right. Please someone explain to me. I don't know what deatiles should I add to shis function. I gues somwone who knows sql well will know this easily
declare #date datetime = '2016-05-01',
#ndays INT = 11,
#country NVARCHAR(2)
BEGIN
IF #date IS NULL
BEGIN
SET #date = GETDATE();
END
IF #country IS NULL
BEGIN
SET #country = 'HU';
END
DECLARE #count INT = 1
DECLARE #newdate datetime
DECLARE #firstdayofmonth date = DATEADD(month, DATEDIFF(month, 0, #date), 0)
WHILE DATEPART(weekday,#firstdayofmonth) in (7,1)
BEGIN
SET #firstdayofmonth = DATEADD(DAY, 1, #firstdayofmonth)
END;
SET #newdate = #firstdayofmonth
WHILE #count < #ndays
BEGIN
SET #newdate = DATEADD(DAY, 1, #newdate)
IF (DATEPART(WEEKDAY, #newdate) not in (1,7))
SET #count += 1;
END
select #newdate
END
I get that this is about declaring a date. The firstdayofmonth calculatio is confusing in it.
This is clearly no mysql code weekday goes from 0 to 6. Also you can't declare variables that way.
Also you should have posted the whole code.
AS for your code:
The first While Clause searches for the first Monday in a Month.
The second counts all Working Days (Monday till Friday) of that chosen Month.
With the first variables, you can manipulate which Month, but what that country has to do with it I can only guess that you have a list of all public holiday fur Hungary.
#newdate becomes the first weekday of the month (Monday-Friday). If the month starts on a weekend (Saturday or Sunday), it shifts up until Monday; otherwise it stays the same. As for the second part, #count looks like it ends up being the number of weekdays in the first eleven days since the start of the first weekday.
I have a start date and end date column in my table and I get a start date and end date as input. I need to set START date as TBL.StartDate if it is after INPUT Start Date and I need to set END date as TBL.EndDate if it is before INPUT End Date. Finally count the days between START and END.
I'm trying to use if statement but I fail when I try to use if in select query.
I'm not sure if this is a correct way of solving this problem.
Declare #Start Date;
Declare #End Date;
Declare #INPUT_StartDate Date;
Declare #INPUT_EndDate Date;
set #INPUT_StartDate = '2019-01-01'; --user input
set #INPUT_EndDate = '2019-04-20'; --user input
select
TBL.StartDate,
TBL.EndDate,
#INPUT_StartDate,
#INPUT_EndDate,
if(TBL.StartDate < INPUT_StartDate) set #Start = TBL.STARTDate;
else set #Start = INPUT_StartDate;
if(TBL.EndDate < INPUT_EndDate) set #End = INPUT_EndDate;
else set #End = TBL.EndDate;
#DateDiff(day, #Start, #End) as COUNT
from TBL
I'm expecting that this comparison happens, but i guess i'm using if statement in between select query is not allowed?
Actual results are quite a few syntax errors near if.
You can make sure of case statement which is same as if but used in case statement. if you want to use if in select list(there is IIF if your sql server is 2012+). If is mostly used in conditional logic.
I removed #start and #end date variable which might not be required based on the logic you are using.
select '2019-03-20' as startdate, '2019-04-20' as ENddate into #temp union all
select '2018-02-01' as startdate, '2019-03-20' as ENddate
Declare #Start Date;
Declare #End Date;
Declare #INPUT_StartDate Date;
Declare #INPUT_EndDate Date;
set #INPUT_StartDate = '2019-01-01'; --user input
set #INPUT_EndDate = '2019-04-20'; --user input
select
TBL.StartDate,
TBL.EndDate,
#INPUT_StartDate INPUT_StartDate,
#INPUT_EndDate INPUT_EndDate,
datediff(day, case when tbl.StartDate < #INPUT_StartDate then TBL.STARTDate
else #INPUT_StartDate end,
case when TBL.EndDate < #INPUT_EndDate then #INPUT_EndDate
else TBL.EndDate end) date_diff
from #temp tbl
Output:
Startdate Enddate Input_startdate input_enddate date_diff
2019-03-20 2019-04-20 2019-01-01 2019-04-20 109
2018-02-01 2019-03-20 2019-01-01 2019-04-20 443
SQL Server doesn't have least() or greatest(). And SQL Server doesn't allow you to mix selecting columns with setting variables.
I recommend setting the values in a "subquery", in this case, using apply:
select t.StartDate, t.EndDate,
#INPUT_StartDate, #INPUT_EndDate,
DateDiff(day, v.dateStart, v.dateEnd) as num_days
from tbl t cross apply
(values (case when t.StartDate < #INPUT_StartDate
then t.STARTDate
else #INPUT_StartDate
end,
case when t.EndDate < #INPUT_EndDate
then INPUT_EndDate
else #TBL.EndDate
end
)
) v(startDate, endDate);
declare #StartDate datetime,#msg varchar(100),#Diff int
declare #EndDate datetime
declare #TodayDate datetime
set #StartDate = '2019-04-23' ---Define Start Date-----
set #EndDate = '2019-04-30' ---Define End Date-----
set #TodayDate = GETDATE()
if(#StartDate < #TodayDate)
begin
set #msg = 'Date is Smaller than today date'
select #msg
end
else
begin
select #Diff = DATEDIFF(day,#StartDate,#EndDate)
set #msg = #Diff
select #msg as Days_Differance
end
I'm getting the error
Invalid parameter 1 specified for dateadd.
when I try to execute the following dynamic parametrized query in SQL Server 2012:
DECLARE #Interval nvarchar(5) = 'DAY'
DECLARE #Increment int = 10
DECLARE #BaseDate date = getdate()
DECLARE #ResultDate date
DECLARE #Query nvarchar(2000)
SET #Query = 'SELECT #result = DATEADD(#Interval, #Increment, CAST(#BaseDate AS DATE))'
EXECUTE sp_executesql #Query,
N'#result date OUTPUT, #Interval varchar(50), #Increment int, #BaseDate date',
#Interval = #Interval, #Increment = #Increment,
#BaseDate = #BaseDate, #result = #ResultDate OUTPUT
SELECT #ResultDate
I've changed the SET #Query line to this one.
SET #Query = 'SELECT #result = DATEADD(' + #Interval +', #Increment, CAST(#BaseDate AS DATE))'
Although it works fine, I'm curious about why the first statement is causing the error in my dynamic SQL query?. Doesn't sp_executesql generate the same statement than the concatenated query one?
So the way to think about parameterized dynamic sql is you can only use a parameter where you could if it were static SQL. DATEADD expects a special date part keyword (e.g. day, hour, year, etc), not a literal string, and not a variable. It's the same issue some people run into where they think they can parameterize something like a table name. The first statement fails because even in static sql, this is invalid:
declare #increment nvarchar(5) = 'day'
select dateadd(#increment, 1, getdate())
That's equivalent to
select dateadd('day', 1, getdate())
The second statement succeeds because you're concatenating the string "day" which gets evaluated to the keyword.
In the first case, the query (with #Interval expanded to its value) becomes this:
SELECT #result=DATEADD('DAY', #Increment, CAST(#BaseDate AS DATE))
and in the second query it becomes this:
SELECT #result=DATEADD(DAY, #Increment, CAST(#BaseDate AS DATE))
The first query is invalid because there the first parameter to DATEADD is a string value, where the compiler expects a language keyword, and those are not the same in SQL.
For more info, see here: https://learn.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql
Please note the line under datepart saying User-defined variable equivalents are not valid. In other words you can't put quotes around these "values", they are not strings but keywords, and they can not be put in variables.
I am trying to create dynamic code for date calculation in SQL stored procedures but am having problems executing string expressions and parameters as date expressions.
I want to hold generic string expressions in a table that will create the dates according to the value of the parameters.
for example this is a generic expression :
DATEADD(#TimeResolution, -#IterationN, #CurrentCalc)
as you can see these generic expressions are composed out of parameters to.
in the stored procedures I intend to declare the variables that are in the expression and assign values to them using a select statement from a different table.
the problem is that after deriving these string values and writing the expression it does not give me the date I want but fails.
so for example if I write the following code
declare #Today date
declare #LastYear date
set #Today = getdate()
set #LastYear = DATEADD(year, -1, #Today)
select #Lastyear
it works fine and I will get last year's date.
but when I try something like this :
declare #Today date
declare #LastYear date
declare #Timeresolution varchar(5)
select #Timeresolution = [Timeresolution] from dbo.mytable where rule_id=1//Timeresolution is a varchar column in my table holding the values 'year' or 'month'
declare Iteration int
select #Iteration = [Iteration] from dbo.mytable where rule_id=1 //Iteration is a int column in my table holding the values 1 or 2, or 3
set #Today = getdate()
set #LastYear = DATEADD(Timeresolution , -Iteration , #Today)
select #Lastyear
this gives me a conversion error.
Is there a way to create such dynamic date expressions?
It isn't possible to use a variable for the interval in DATEADD, but you can do something like this:
IF #Timeresolution = 'year'
BEGIN
SET #LastYear = DATEADD(year, -#Iteration , #Today)
END
IF #Timeresolution = 'month'
BEGIN
SET #LastYear = DATEADD(month, -#Iteration , #Today)
END
I tried to figure out a dynamic query to get date col within past 20 days. The idea is quite simple and, moreover, I know the table does contain dates from getdate() to -20 days but still no result get returned
DECLARE #date_past_period varchar(MAX);
DECLARE #date_past_number varchar(MAX);
SET #date_past_period='day';
SET #date_past_number='20';
DECLARE #aDate datetime;
DECLARE #sql varchar(MAX);
SET #sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,getdate(),121) AND convert(varchar,dateadd('+#date_past_period+', -'+#date_past_number+', getdate()),121)';
exec(#sql);
Maybe the problem is in dynamic thing but I am not sure.
Any useful comment is appreciated
You can use CASE function (T-SQL):
CREATE PROCEDURE MyStoredProcedure
#IntervalType VARCHAR(15),
#Num INT
AS
DECLARE #StartDate DATETIME = GETDATE();
DECLARE #EndDate DATETIME =
CASE #IntervalType
WHEN 'DAY' THEN DATEADD(DAY,#Num,#StartDate)
WHEN 'MONTH' THEN DATEADD(MONTH,#Num,#StartDate)
WHEN 'YEAR' THEN DATEADD(YEAR,#Num,#StartDate)
END;
IF #EndDate IS NULL
RAISERROR('Invalid params', 16, 1);
ELSE
SELECT date FROM table WHERE date BETWEEN #StartDate AND #EndDate;
By converting to VARCHAR your search condition from WHERE will not be SARG ( 1 & 2 ).
I am pretty sure this scenario can be covered without using dynamic SQL, however, one obvious problem in your SQL is the between clause - the range is in the wrong order. Try changing your #sql as below:
SET #sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,dateadd('+#date_past_period+', -'+#date_past_number+', getdate()),121) AND convert(varchar,getdate(),121)';