SQL Server : calculating days elapsed - sql-server

I need to get the number of elapsed days between any two dates with respect to the current date. IE:
mm/dd/yyyy
Current day = 07/10/2015
07/08/2013 ... 07/11/2013 - 4 days elapsed
Current day = 07/10/2015
07/08/2015 ... 07/11/2015 - 2 days have elapsed
I've tried several combinations using DATEDIFF with day as the date part, however, I can't seem to get a clean way to get the days elapsed when the date could be past or present.
EDIT
I know the start date and the end date of a certain business process. They could be this year, last year, two years ago and so on. I need a way via SQL Server functions to figure out the days total elapsed. If it's not the current year, obviously the entire span/range would have elapsed. If it's the current year, perhaps the entire span/range hasn't elapsed and it needs to say how many days are "into the process" based on the respected start time, end time and current time.
Hopefully this makes more sense?
Please help.
I used #Sean Lange, with a small tweak:
DATEDIFF(DAY, #StartDate, case when #EndDate < GETDATE() then #EndDate + 1 else GETDATE() end)
Thanks all.

This is pretty similar to the answer provided by Stan but here is my take on this.
with Something as
(
select CAST('2013-07-08' as datetime) as StartDate
, CAST('2013-07-11' as datetime) as EndDate
union all
select '2015-07-08', '2015-07-11'
)
select *
, DATEDIFF(DAY, StartDate, case when EndDate < GETDATE() then EndDate else GETDATE() end)
from Something

How about this:
Given:
CREATE TABLE dbo.test ( ChildID INT Identity,
Start DateTime
, Finish DateTime
)
and your test data:
insert into dbo.test (start,finish) values('07/08/2013','07/11/2013')
insert into dbo.test (start,finish) values('07/08/2015','07/11/2015')
then
select start,finish
, DATEDIFF(DAY, start, CASE WHEN GETDATE() BETWEEN start and finish
THEN GETDATE() - 1 ELSE finish END) + 1 as elapsed
from dbo.test
gives the result from your example.
You might have to tweak if there are other adjustments for how the current date fits between the range.

Related

How to find the past 4 weeks of the same weekday value starting today

I am trying to select records from today and the same day of each week for the last 4 weeks.
Today (Tuesday)
Last Tuesday
The Tuesday before that
The Tuesday before that
I need this to be tied to current date because I am going to run this query every day so I don't want to use a between or something where I manually specify the date range.
Everything I have found or tried so far has pulled the last month of data but not the last 4 weeks of the same weekday.
select *
from table
where thedatecolumn >= DATEADD(mm, -1, GETDATE())
This works but pulls everything from the last month.
If today's date is 7/10/2019 I need
Data from 7/10/2019
Data from 7/3/2019
Data from 6/26/2019
Data from 6/19/2019
Every day I will run this query, so I need it to be dynamic based on the current date.
I believe you want to look back 21 days and then filter those dates that have the same day of week:
select * from table
where thedatecolumn >= DATEADD(DAY, -21, CAST(GETDATE() AS DATE))
and DATEPART(WEEKDAY, thedatecolumn) = DATEPART(WEEKDAY, GETDATE())
You Can try using a recursive cte which starts today and repeatedly substracts 7 days - so you ensure you always land on the same weekday. Following an example:
WITH cteFromToday AS(
SELECT 0 AS WeeksBack, GETDATE() AS MyDate
UNION ALL
SELECT WeeksBack + 1 AS WeeksBack, DATEADD(d, -7, MyDate) AS MyDate
FROM cteFromToday
)
SELECT TOP 5 *
FROM cteFromToday
OPTION ( MaxRecursion 0 );
This is quite simple. Substitute CURRENT_TIMESTAMP here for any given date.
SELECT CONVERT(DATE,CURRENT_TIMESTAMP) AS Today,
DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)) AS LastWeek ,
DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)) AS TwoWeeksAgo,
DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP)) AS ThreeWeeksAgo
SO, if you want to get data for a set of ranges for one entire day with those dates:
SELECT something
WHERE
datetimecolumn >= CONVERT(DATE,CURRENT_TIMESTAMP) AND datetimecolumn < DATEADD(DAY,1, CONVERT(DATE,CURRENT_TIMESTAMP)) -- Todays range,
OR datetimecolumn >= DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1,DATEADD(DAY,-7,CONVERT(DATE,CURRENT_TIMESTAMP)))-- LastWeek ,
OR datetimecolumn >= DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1,DATEADD(DAY,-14,CONVERT(DATE,CURRENT_TIMESTAMP)))-- TwoWeeksAgo,
OR datetimecolumn >= DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP)) AND datetimecolumn < DATEADD(DAY,1, DATEADD(DAY,-21,CONVERT(DATE,CURRENT_TIMESTAMP))) -- ThreeWeeksAgo

SQL Server : DATEDIFF not accurate

I'm trying to retrieve the month difference of two dates but it seems like I can't find a way to get the accurate months.
Here are the queries I tried so far :
SELECT DATEDIFF(month,convert(datetime, '11/05/2015'), convert(datetime, '12/06/2015')) - 1
This will result to 0 which is wrong and when I used another date :
SELECT DATEDIFF(month,convert(datetime, '12/31/2015'), convert(datetime, '01/01/2016')) - 1
This would yield to 0 which is correct.
Leap year must also be considered.
The TSQL is return the correct results as you have written them. As you have it, it is taking the difference of the months between the two dates specified.
SELECT DATEDIFF(month, convert(datetime, '11/05/2015'), convert(datetime, '12/06/2015'))
The difference, in months, between November and December is "1".
However, if you are wanting the difference in terms of every 30 days is 1 month, then you would need to rewrite your query:
declare #daysPerMonth int = 30
SELECT (DATEDIFF(day, convert(datetime, '11/05/2015'), convert(datetime, '12/06/2015')) / #daysPerMonth)
This works if you define the number of days in a month as 30.
Here is a way to visualize what DATEDIFF(month, ...) is doing. Think of a monthly calendar hanging on the wall. For the purposes of this particular SQL function "number" of months between two dates is the number of pages you have to flip to get from one date to the next. It doesn't matter how many days are in each month or whether it's a leap year.
You aren't the first person to be confused about the behavior of the built-in function. If you need to count months by a different method then you'll need to describe the specifics of what you want to accomplish. It's very likely that a solution will be easy to create once you define the problem that needs to be addressed.
In T-SQL you can use CASE:
SELECT DATEDIFF(month, convert(datetime, '11/05/2015'),
convert(datetime, '12/06/2015')) -
CASE
WHEN (MONTH('11/05/2015') > MONTH('12/06/2015')
OR MONTH('11/05/2015') = MONTH('12/06/2015')
AND DAY('11/05/2015') > DAY('12/06/2015'))
THEN 1 ELSE 0
END
Which returns 1 which is correct and:
SELECT DATEDIFF(month, convert(datetime, '12/31/2015'),
convert(datetime, '01/01/2016')) -
CASE
WHEN (MONTH('12/31/2015') > MONTH('01/01/2016')
OR MONTH('12/31/2015') = MONTH('01/01/2016')
AND DAY('12/31/2015') > DAY('01/01/2016'))
THEN 1 ELSE 0
END
Which returns 0 which is correct.
declare
#start date = '20220105',
#end date = '20220406'
select 'Date_Diff_In_3 months' =
case
when datediff(month, #start, #end) < 3
or (datediff(month, #start, #end) = 3 and day(#start) >= day(#end))
then 'yes'
else 'no'
end

Getting plot data from date-range efficiently

I'm trying to create utilization graph for a telephone system. I have sets of data which is in the table format
ID *
StartDate
EndDate
From
To
What I'm trying to do is get SQL to to output me a list of plot points every 5 minutes, so basically
The count of active calls (between StartDate and EndDate) for every 5 minutes in a day.
The result beign something like
Date Time Count
2000-01-01 00:00:00 10
2000-01-01 00:05:00 2
2000-01-01 00:10:00 7
Can anyone suggest a way to generate said data? I'm at a loss here! The stuff I've been thinking abut all involves a creating a big loop and running a query for every 5 seconds which seems super inefficient.
The method I was originally thinking was :-
storedProc GetSamples(SampleStartDate, SampleEndDate)
Create memory table for result data
for every 5mins as sample between SampleStartDate and SampleEndDate
SELECT #SampleCount = COUNT(1) FROM Samples where 5mins BETWEEN StartDate AND EndDate
UPDATE memoryTable SET count=#SampleCount WHERE time = 5mins
end
end
If you have a recent enough version of SQL Server (2008+), you ought to be able to do this with a CTE joined to your phone call log, like this (CTE base found here):
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = '2000-01-01 00:00:00.000'
SET #EndDate = '2000-01-02 00:00:00.000'
;WITH DateSequence( [PlotPointDate] ) AS
(
SELECT #StartDate AS [PlotPointDate]
UNION ALL
SELECT DATEADD(MINUTE, 5, [PlotPointDate] )
FROM DateSequence
WHERE [PlotPointDate] < #EndDate
)
--select result
SELECT
PlotPointDate, COUNT(YourTable.ID) AS TotalActiveCalls
FROM
DateSequence
LEFT JOIN
YourTable ON
YourTable.StartDate <= DateSequence.PlotPointDate AND
(YourTable.EndDate >= DateSequence.PlotPointDate OR YourTable.EndDate IS NULL)
GROUP BY PlotPointDate
OPTION (MaxRecursion 10000)

DATEADD with part days

I'm having a little trouble getting a count of dates in SQL SERVER. I require the number of calender days between 2 dates start and ends dates included. The problem with the example below is that it always returns 10 when I believe it should be 11.
DECLARE #FROM DATETIME, #TO DATETIME
SET #FROM = '18/12/2011 00:00:00'
SET #TO = '28/12/2011 00:00:00'
SELECT
DATEDIFF(MINUTE,#FROM,#TO), -- Returns 14459
DATEDIFF(HOUR,#FROM,#TO), -- Returns 241
DATEDIFF(DAY,#FROM,#TO), -- Returns 10
CEILING(CAST((DATEDIFF(HOUR,#FROM,#TO) / 24) as DECIMAL(9,5))) --Returns 10
CEILING(CAST(CEILING(CEILING(CAST(DATEDIFF(SECOND,#FROM,#TO) as DECIMAL(18,5))) / 60) / 60 as DECIMAL(9,5)) / 24) --Returns 10
The bottom line works if there is at least 1 second between the times but I must account for all scenarios.
My only other thought was to simply add one to the date diff to account for the part days? Is that reliable?
DATEDIFF(DAY,#FROM,#TO) + 1
I came across when answering this question How to find the total between the dates for each values
Is an expression that can be resolved to a time, date, smalldatetime,
datetime, datetime2, or datetimeoffset value. date can be an
expression, column expression, user-defined variable or string
literal. startdate is subtracted from end date.
This is taken from MSDN here.
28-18 = 10. I think you will always have to add 1 in the scenario you have because of the definition for DATEDIFF.
You need to set the #TO date to:
SET #TO = '28/12/2011 23:59:59'
To get the number of days between two dates (ignoring the time of day), including the start and end date, try;
SELECT FLOOR(CONVERT(FLOAT, #TO))-FLOOR(CONVERT(FLOAT, #FROM))+1
Edit:
SELECT DATEDIFF(d, #FROM, #TO)+1
seems to return the exact same results, which would indeed make it a more elegant way of doing it. Always thought DATEDIFF timeparts were about truncating after the calculation (which would give the wrong result if the start time was later in the day than the end time) and not truncating before the calculation which gives the correct result for your case. You learn something new every day :)
If you want a close equivalent of the C# DateTime.TotalDays() function (i.e. to know fractional days) you can use the following:
DECLARE #start DATETIME = '10 Apr 2012 15:00'
DECLARE #end DATETIME = '12 Apr 2012 16:00'
SELECT CONVERT(FLOAT, DATEDIFF(SECOND, #start, #end)) / 86400
*Note: 86400 = seconds in a day = 24 hours x 60 mins x 60 seconds

SQL QUERY ( SQL SERVER) Date & Time Difference

I have a SQL SERVER Table which has only one field "StartDate" the records are as follows
**
2011-07-28 19:30:00.000
2011-07-29 21:50:00.000
2011-07-25 09:20:00.000
**
What i want to do is :
SHOW RECORDS if its CURRENT DATE ( todays date ) and the time difference between current time the StartDate is not less then 5 minutes, i have written the following code but it doesnt show me the time difference ?
SELECT * FROM table WHERE DATEDIFF(day, StartDate, GETDATE()) <= 0
SELECT StartDate
FROM table
WHERE YEAR(StartDate)=YEAR(GETDATE())
AND MONTH(StartDate)=MONTH(GETDATE())
AND DAY(StartDate)=DAY(GETDATE())
AND (DATEDIFF(minute, StartDate, GETDATE()) >= 5
OR
DATEDIFF(minute, StartDate, GETDATE()) <= 5)
How about:
SELECT StartDate
,GETDATE()
,DATEDIFF(day, StartDate, GETDATE())
,DATEDIFF(minute, StartDate, GETDATE())
,*
FROM table
WHERE DATEDIFF(day, StartDate, GETDATE()) <= 0
AND DATEDIFF(minute, StartDate, GETDATE()) >= 5
There are two ways to do it one being DateDiff the other is DATEADD. Judging by the way I read your question DateAdd should do it. Here is an example;
SELECT *
FROM [dbo].[TABLE]
WHERE [LAST_UPDATE] > DATEADD(minute,-5,GetDate())
Using BETWEEN is probably a little more optimal than two AND statements (maybe not). Try not to do a calculation on each row if you don't have to. Doing DATEADD only on the current date will only be calculated once.
SELECT
whatever
FROM
table
WHERE
StartDate
BETWEEN FLOOR( CAST( GETDATE() AS FLOAT ) )
AND DATEADD(minute, -5, GETDATE())
I interpret the question as looking for rows where the date is today (between the start of today) but not within the last 5 minutes (and less than 5 minutes ago). That might not be what you were going for.
Hope that helps

Resources