Using T-SQL DATEADD and DATEDIFF function - sql-server-2008

I am trying to understand the code that someone wrong to implement the following requirements in calculating a date:
The derived JE_ACCTNG_DT is set equal to the last day of the prior month of the current year when the feed is created and sent.
For example, if the current year is 2013, the JE_ACCTNG_DT will be the following based on the quarter the feed is sent:
JE_ACCTNG_DT = 3/31/2013 for 1st quarter feed sent on 4/1/2013
JE_ACCTNG_DT = 6/30/2013 for 2nd quarter feed sent on 7/1/2013
JE_ACCTNG_DT = 9/30/2013 for the 3rd quarter feed sent on 10/1/2013
JE_ACCTNG_DT = 12/31/2013 for the 4th quarter feed sent on 1/1/2014
I see that someone implemented the code like this and it seems to give the right answer for the examples given in the requirements, if the datetime result is converted to a date data type (the time portion is dropped)
DECLARE #FEED_DT datetime
SET #FEED_DT = '4/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#FEED_DT),0))
SET #FEED_DT = '7/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#FEED_DT),0))
--2013-06-30 23:59:59.000
SET #FEED_DT = '10/1/2013'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#FEED_DT),0))
--2013-09-30 23:59:59.000
SET #FEED_DT = '1/1/2014'
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#FEED_DT),0))
--2013-09-30 23:59:59.000
What is confusing me is that the DATEDIFF function accepts the following arguments: A datepart and two dates
DATEDIFF (datepart ,startdate ,enddate )
If you notice above, the code set the date part to "m" but passed zero for the 2nd parameter when a date is expected.
DECLARE #FEED_DT datetime = '4/1/2013'
DECLARE #DateAddResult as int
SET #DateAddResult = DATEDIFF(m,0,#FEED_DT)
select #DateAddResult
--1359
select DATEADD(s,-1,DATEADD(mm, #DateAddResult,0))
--2013-03-31 23:59:59.000
What is the code really doing? I would've expected an error. Did it coerce the 0 value to a date?
I'm thinking that what the requirements should really be is to calculate the last day of the previous quarter. This is how I would do it.
SELECT dateadd(day, -1, DATEADD(quarter,DATEDIFF(quarter,'1900/01/01', GETDATE()), '1900/01/01')) as FirstDayOfQuarter

Given this:
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#FEED_DT),0))
Let's take it one piece at a time...
DATEDIFF(m,0,#FEED_DT)
...calculates the number of whole integer months that has alapsed from date value zero (which is evaluated as 1-1-1900) to the date value started in the datetime field #FEED_DT. Let's say that this value is #ElapsedMonthsSinceZero and replace this variable into the original nested function, giving:
select DATEADD(s,-1,DATEADD(mm, #ElapsedMonthsSinceZero,0))
Now let's evaluate this part:
DATEADD(mm, #ElapsedMonthsSinceZero,0)
This adds the same number of months to the Date "zero", i.e. 1-1-1900, which brings you to the first day of the month of the date #FEED_DT. Essentially, what we did so far was calculate the whole number of months that have elapsed from date 0, truncating off any day beyond day 1 into the month. This gives us #FirstDayOfFEED_DT. Replacing that into the function gives us...
select DATEADD(s,-1,#FirstDayOfFEED_DT)
Now that we have the first day of the month of the date #FEED_DT, subtracting 1 gives us the last day of the previous month.
I guess I was just thrown off by the discrepancy where a value of 0 was passed instead of a date.

suppose you add some days in a new column and you hava a stored procedure of a parameter #date and you want to add current date to that parameter and get result in days.
DateAdd(days,#date,Getdate())

Related

DATEDIFF function displayed error output in sqlserver

i tried the code in mysql it is working well
select car_id,cust_id,due,DATEDIFF(NOW(),due) as elap from rental where car_id = '1'
issue date 2019-10-16 return date 2019-10-17
have to calucalated elap result displayed in -1 it is working well.
if i tried in sqlserver it produced wrong output
select cat_id,cust_id,date,due,DATEDIFF(dd,GETDATE(),due) as elap from rental where cat_id = '1'
have to calucalated elap result displayed in 1.wrong output right on is -1 i don't know what is the error on sqlserver code
SQL Server's DATEDIFF function uses the format:
DATEDIFF(datepart, start_date, end_date)
It returns the difference between the ending date and the starting date, in that order. So, in your example, if the due date is one day past the current date, you would get a date diff of +1.
MySQL's DATEDIFF computes the difference in the opposite order, namely taking the first date minus the second date, i.e.
DATEDIFF(date1, date2)
this would return the number of days which elapsed from date2 to get to date1, i.e. date1 - date2.
This will work correctly.
select cat_id,cust_id,date,due,DATEDIFF(dd,due,GETDATE()) as elap from rental where cat_id = '1'

SSRS Prior Month, MTD Same period as current month -1 Day

If today is 5/2 I want to see last month's data for 4/1.
For tomorrow on 5/3 I want to see last month's data for 4/2, etc
I want to modify the code to not show me today's value for same time last month, I want the day before today.
I got this far from another question asked here.
SSRS Prior Month, MTD Same period as current month
=sum(IIf(Year(Fields!AppDateActualDate.Value) = Year(DateAdd("d",-1, Now).AddMonths(-3)) And Month(Fields!AppDateActualDate.Value) = Month(DateAdd("d",-1, Now).AddMonths(-3)) AND DatePart("d", Fields!AppDateActualDate.Value) <= Dateadd("d",-1, Now), Fields!Application_Count.Value, Nothing), )
I'd create a new data set (assuming you are using SQL as your data source) and create a default date you are after.. simple as this:
select dateadd(day,-1, dateadd(month,-1, convert(date,getdate()))) as default_date
Then use this date as your parameter for your report.
That is the start date.. not clear as to what you want your end date to be..

MS Access DateDiff Ambiguous Dates (Day Month order) Returning bad results

tblDurations
TaskID : Number
Assigned Date : Date/Time
Start Date : Date/Time
End Date : Date/Time
SELECT TaskID,
Count(TaskID) As [Task Count],
Min(Nz([Start Date], [Assigned Date])) as [Min of Start Date],
Max([End Date]) as [Max of End Date],
DateDiff("d", Min(Nz([Start Date], [Assigned Date])), Max([End Date])) + 1 as [Date Range]
FROM tblDurations
GROUP BY TaskID
Output:
TaskID Task Count Min of Start Date Max of End Date Date Range
1 3 16/08/2018 10/01/2019 1
2 2 4/09/2017 07/09/2017 4
3 3 13/09/2017 08/01/2018 118
I am getting the occasional row as shown in row 1 (TaskID = 1) which should equal 148!
After a lot of checking I determined this occurs for dates that are ambiguous. By that I mean where the day and months values can be confused for each other.
I'm in Australia where the date formnat is dd/mm/yyyy. However I believe the datediff function is confusing the day and month order and returning Zero (plus my 1 = 1).
How can I overcome this issue?
The problem was not the ambiguous dates. Looking closer I found various non ambiguous dates returning bad values.
The problem was the use of an Nz function which I was using like this :
Min(NZ([Start Date], [Assigned Date]))
Which I took to mean take the Min of either the Start Date, but if the start date does is NULL then the min of the Assigned Date.
What does work is this :
Nz(Min([StartDate], Min(Assigned Date))
All fixed.
Which begs the question. Why only sometimes? As it was not related to Start Dates being NULL or not NULL.
Thanks everyone for feed back!

check if in existing result set all days within month are present

How can I check if in my result set (which is formed by query shown below at the end) for every month exists every day? For example in below result set:
Date_List
08/01/2016
08/02/2016
08/03/2016
08/04/2016
08/05/2016
08/06/2016
08/07/2016
08/08/2016
08/09/2016
08/10/2016
08/11/2016
08/12/2016
08/13/2016
08/14/2016
08/15/2016
08/16/2016
08/17/2016
08/18/2016
08/19/2016
08/20/2016
08/21/2016
08/22/2016
08/23/2016
08/24/2016
08/25/2016
08/26/2016
08/27/2016
08/28/2016
08/29/2016
08/30/2016
08/31/2016
We can see that August 2016 has all days available. I want to return only such months (with all days available) with a year part of course. In this case it would be 08/16 (MM/YYYY) to return. Thus if any day for any month is missing - I do not want to return such month.
Here is the query I use to form result set:
SELECT d.`Date_List` FROM staging_area.`g360_dates_ca` d
LEFT JOIN dm_research_development.g360_pro_saas_availability a
ON d.`Date_List` = a.`DATE_OCCURRED_DATE` AND a.`IS_OUTAGE` = 'YES'
WHERE a.`DATE_OCCURRED_DATE` IS NULL AND STR_TO_DATE(d.`Date_List`,'%m/%d/%Y') <= NOW();
g360_dates_ca table contains all dates starting 01-01-2013 till 01-01-2018.
g360_pro_saas_availability - is my incidents table with details.

VBA: DateDiff Year off

I have the following code in VBA to return the year between two dates: DateDiff("yyyy", "10/10/1930","06/07/2008 8:30:00 AM")
It returns 78, but it should really be 77.
What is going on here?
VBA's DateDiff function was not designed to track elapsed time. That statement is simply evaluating the year.
See this msdn article, which offers a function to calculate the years elapsed: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvbadev/html/workingwithelapsedtime.asp
Function elapsed_years_function(first_date As Date, Optional second_date As Date = 0) As Integer
' This procedure is from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvbadev/html/workingwithelapsedtime.asp
Dim elapsed_years As Integer
If second_date = 0 Then
' Did the caller pass in a date? If not, use
' the current date.
second_date = Date
End If
elapsed_years = DateDiff("yyyy", first_date, second_date)
If second_date < DateSerial(Year(second_date), Month(first_date), Day(first_date)) Then
elapsed_years = elapsed_years - 1
End If
elapsed_years_function = elapsed_years
End Function
Edit: According to this (VB.Net) As pointed out by #Justin, this is for VB.Net, not Visual Basic, but the implementation is most likely identical for backwards compatibility. I've referenced the relevant VBScript documentation below for completeness.
Larger Intervals. If Interval is set
to DateInterval.Year, the return value
is calculated purely from the year
parts of Date1 and Date2. Similarly,
the return value for
DateInterval.Month is calculated
purely from the year and month parts
of the arguments, and for
DateInterval.Quarter from the quarters
containing the two dates.
For example, when comparing December
31 to January 1 of the following year,
DateDiff returns 1 for
DateInterval.Year,
DateInterval.Quarter, or
DateInterval.Month, even though at
most only one day has elapsed.
Also see this (VBScript):
When comparing December 31 to January
1 of the immediately succeeding year,
DateDiff for Year ("yyyy") returns 1
even though only a day has elapsed.
So it's likely implemented like this, which gives 78:
Year(SecondDate) - Year(FirstDate)
See #Ken's solution for an implementation that should work as intended.
If you did DateDiff("yyyy", "12/31/2010", "1/1/2011") it would return 1, even though there is only a day difference.
Working as designed: see Remarks (larger intervals) under http://msdn.microsoft.com/en-us/library/b5xbyt6f%28v=vs.80%29.aspx WHICH STATES:
If Interval is set to DateInterval.Year, the return value is calculated purely from the year parts of Date1 and Date2.
When you do datediff by year the operation performed is 2008 - 1930