Sql datetime calculation - sql

I have an Excel sheet and have this formula below. I would like to calculate the same formula with sql. The result will be in second.
Thank you,
declare #t1 AS datetime
declare #t2 AS datetime
declare #t3 AS datetime
declare #t4 AS datetime
set #t1 = '2011-11-04 00:00:00.000' --start date
set #t2 = '2012-01-16 18:21:55.000' --start time
set #t3 = '2011-11-10 00:00:00.000' --end date
set #t4 = '2012-01-16 12:10:00.000' --end time
Excel formula
((end date-start date-1)+(end time-(0,375)))*24*60*60
0,375 value means 9 hour
formula result will be = 443400 second

You mention that you not using Start Time in your formula?
Here it comes:
declare #t1 AS datetime
declare #t2 AS datetime
declare #t3 AS datetime
declare #t4 AS datetime
set #t1 = '2011-11-04 00:00:00.000' --start date
set #t2 = '2012-01-16 18:21:55.000' --start time
set #t3 = '2011-11-10 00:00:00.000' --end date
set #t4 = '2012-01-16 12:10:00.000' --end time
SELECT CAST((DATEDIFF(d, #t1, #t3)-1 + (CAST(#t4 AS FLOAT) - FLOOR(CAST(#t4 AS FLOAT)) - 0.375))*24*60*60 AS INT)

Related

Issue while calculating SLA in SQL

I am using below function to calculate the elapsed time between 2 input timestamps. Only time spent during business hours should be calculated. Business hrs are Mon-Sat 8 am to 6 pm.
Function call syntax:
select xxxxx('2018.09.28 19:02:28','2018-09-29 10:40:35') Function is giving output as 98 mins, the correct answer is 160 mins.
Function structure is:
Create FUNCTION xxxxx (#LeadAssignTime DATETIME, #LeadContactTime DATETIME)
RETURNS VARCHAR(9)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp=0
DECLARE #LeadAssignDay VARCHAR(9)
SET #LeadAssignDay = CONVERT(VARCHAR(9),#LeadAssignTime, 112)
DECLARE #LeadContactDay VARCHAR(9)
SET #LeadContactDay = CONVERT(VARCHAR(9),#LeadContactTime, 112)
DECLARE #StartTime VARCHAR(9)
SET #StartTime = CONVERT(VARCHAR(9),#LeadAssignTime, 108)
DECLARE #FinishTime VARCHAR(9)
SET #FinishTime = CONVERT(VARCHAR(9),#LeadContactTime, 108)
DECLARE #WorkStart VARCHAR(9)
SET #WorkStart = '08:00:00'
DECLARE #WorkFinish VARCHAR(9)
SET #WorkFinish = '18:00:00'
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
DECLARE #CurrentDate VARCHAR(9)
SET #CurrentDate = CONVERT(VARCHAR(9),#LeadAssignTime, 112)
DECLARE #LastDate VARCHAR(9)
SET #LastDate = CONVERT(VARCHAR(9),#LeadContactTime, 112)
WHILE(#CurrentDate<=#LastDate)
BEGIN
IF (DATEPART(dw, #CurrentDate)!=1 )
BEGIN
IF (#CurrentDate!=#LeadAssignDay) AND (#CurrentDate!=#LeadContactDay)
BEGIN
SET #Temp = (#Temp + (8*60))
END
ELSE IF (#CurrentDate=#LeadAssignDay) AND (#CurrentDate!=#LeadContactDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#LeadAssignDay) AND (#CurrentDate=#LeadContactDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
ELSE IF (#CurrentDate=#LeadAssignDay) AND (#CurrentDate=#LeadContactDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = CONVERT(VARCHAR(9),DATEADD(day, 1, #CurrentDate),112)
END
Return #TEMP
END
You're going around your loop twice, but in the first iteration, you fall into the second IF block and setting #temp to be -62
In the second iteration, you fall into the third IF block and calculate 160 for the difference between #WorkStart and #FinishTime, but then this is added to the value already in #Temp. 160-62 = 98.
You'll need your second IF block to check if 'start time' is before 'work finish' before executing that logic.
(#CurrentDate=#LeadAssignDay) AND (#CurrentDate!=#LeadContactDay)
needs to become
(#CurrentDate=#LeadAssignDay) AND (#CurrentDate!=#LeadContactDay) AND ( #StartTime < #WorkFinish)
I haven't done any vetting beyond the one use case. Make sure to do some thorough testing.

Displaying the number of valid results for a range of dates

I currently have a table with a creation date and a expiry date. I currently have a sql command to get the number of valid items for a given date.
select
count(id) ,CONVERT(date, getdate())
from
table
where
createDate < getdate() and expDate > getdate()
This returns the count and current date.
Is it possible to wrote a sql query that will return the result for a range of dates, say I if wanted to plot the number of valid items over a range of 15 days?
Thanks!
Try this:
create table #datelist (ValidDateCheck date, ValidResults int)
declare #startdate date = '1/1/2015'
declare #enddate date = '2/1/2015'
declare #interval int = 1 --Use 1 if you want every day between your dates, use 2 if you want every other day, etc.
declare #datecounter date = #startdate
declare #count int
while #datecounter <= #enddate
begin
set #count =
(select count(*)
from Table
where CrtDt <= #datecounter and ExpDt > #datecounter)
insert into #datelist values (#datecounter, #count)
set #datecounter = dateadd(dd, #interval, #datecounter)
end
select * from #datelist order by 1
It loops through all the dates in your range, counting valid results for each one.
Check this,
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20110501'
,#EndDate = '20110801';
SELECT
DATEADD(d, x.number, #StartDate) AS MonthName1
,
x.number
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate);
The above query give the list of dates between 2 dates.
As per your table and question, check this also.
declare #table table(id int,frdt datetime, todt datetime)
insert into #table values (1,GETDATE()-20, GETDATE()-19)
,(2,GETDATE()-9, GETDATE()-8)
,(3,GETDATE()+20, GETDATE()+18)
,(4,GETDATE(), GETDATE()-1)
,(5,GETDATE()-20, GETDATE())
,(6,GETDATE()-10, GETDATE()+10 )
select * from #table
declare #frdt datetime = null , #todt datetime = getdate()-10
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)
select #frdt = GETDATE()-15 , #todt = GETDATE()
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)

Can some please help me and show me what I'm doing wrong

CREATE TABLE DateRange
([Date] DATETIME, IsFutureOrPast BIT)
DECLARE #Date AS DATETIME
SET #DATE ='2014-01-01 00:00:00.000'
WHILE #DATE <='2014-12-31 00:00:00.000'
BEGIN
INSERT INTO DateRange ([DATE])
VALUES (#DATE)
SET #Date = #Date + 1
END
--Case Statement to check values and enter flag
DECLARE #CurrentDate AS DATETIME = GETDATE()
UPDATE
DateRange
SET [DATE] =
CASE
WHEN #CurrentDate <= [DATE] THEN 0
ELSE 1
END AS IsPastOrFuture
FROM DateRange
WHERE [Date] IN ( 0, 1)
You're trying to set the DATE field when you should be setting the IsFutureOrPast field:
UPDATE
DateRange
SET [IsFutureOrPast] =
CASE WHEN #CurrentDate <= [DATE] THEN 0
ELSE 1
END
But you could also combine the two statements:
INSERT INTO DateRange ([DATE], [IsFutureOrPast])
VALUES (
#DATE,
CASE WHEN GETDATE() <= #DATE THEN 0 ELSE 1 END
)
SET #Date = #Date + 1
Try this:
DECLARE #DateRange TABLE
([Date] DATETIME, IsFutureOrPast BIT)
DECLARE #Date AS DATETIME
SET #DATE ='2014-01-01 00:00:00.000'
WHILE #DATE <='2014-12-31 00:00:00.000'
BEGIN
INSERT INTO #DateRange ([DATE])
VALUES (#DATE)
SET #Date = #Date + 1
END
--Case Statement to check values and enter flag
DECLARE #CurrentDate AS DATETIME = GETDATE()
UPDATE
#DateRange
SET IsFutureOrPast =
CASE
WHEN #CurrentDate <= [DATE] THEN 0
ELSE 1
END
FROM #DateRange
SELECT * FROM #DateRange
I think you are trying to SET the IsPastOrFuture column
DECLARE #CurrentDate AS DATETIME = GETDATE()
UPDATE
DateRange
SET
IsPastOrFuture = CASE
WHEN #CurrentDate <= [DATE] THEN 0
ELSE 1
END

SQL Separate hours in Start and EndDate

I'm need a help to create a Query. My problem is I have a StartDate and EndDate and need separate this in blocs of 60 minutes.
DECLARE #STARTDATE AS SMALLDATETIME
DECLARE #ENDDATE AS SMALLDATETIME
SET #STARTDATE = '2012-11-21 11:03:00'
SET #ENDDATE = '2012-11-21 13:04:00'
I need the return:
Hour, Time
11 , 57
12 , 60
13 , 04
You could use a recursive CTE. For example:
declare #startDate datetime = '2012-11-21 22:05:00'
declare #endDate datetime = '2012-11-22 01:06:00'
; with TimeList as
(
select #startDate as dt
union all
select dateadd(hour, 1, dateadd(hour, datediff(hour, 0, dt), 0))
from TimeList
where dateadd(hour, 1, dt) < #endDate
)
select dt
from TimeList
union all
select #endDate
The snippet dateadd(hour, datediff(hour, 0, dt), 0) removes the hours and minutes from a date. It does so by calculating the number of hours since date 0 and then adding that number of hours to date 0.
Live example at SQL Fiddle.
I unsure if i understood you but this will return the hour and minute after your start date at 60 min intervals.
DECLARE #STARTDATE AS SMALLDATETIME
DECLARE #ENDDATE AS SMALLDATETIME
DECLARE #time AS TABLE(id int identity(1,1), [hour] int, [time] int)
SET #STARTDATE = '2012-11-21 11:03:00'
SET #ENDDATE = '2012-11-21 13:04:00'
WHILE #STARTDATE < #ENDDATE
BEGIN
SELECT #STARTDATE = DATEADD(MINUTE,60,#STARTDATE)
INSERT INTO #time (hour,time)
VALUES(DATEPART(HOUR,#STARTDATE),DATEPART(MINUTE,#STARTDATE))
END
SELECT * FROM #time
You coan do it in three pieces. First piece is for the first hour, 60 minus the minute value, 2nd piece is time=60 for all hours between start+1 and end, third piece is end minutes
and then insert them into a temp table, as abstractChaos has done.
Insert into temp table like AbstractChaos:
DECLARE #STARTDATE AS SMALLDATETIME
DECLARE #ENDDATE AS SMALLDATETIME
DECLARE #TIME AS TABLE(id INT IDENTITY(1,1), [HOUR] INT, [TIME] INT)
SET #STARTDATE = '2012-11-21 11:03:00'
SET #ENDDATE = '2012-11-21 13:04:00'
INSERT INTO #TIME (HOUR,TIME)
VALUES (datepart(HOUR,#startdate) ,60 - datepart(MINUTE,#startdate) )
WHILE #STARTDATE < #ENDDATE
BEGIN
SELECT #STARTDATE = DATEADD(MINUTE,60,#STARTDATE)
INSERT INTO #TIME (HOUR,TIME)
VALUES(datepart(HOUR,#STARTDATE) , 60)
END
INSERT INTO #TIME (HOUR,TIME)
VALUES(datepart(HOUR,#enddate) , datepart(MINUTE,#startdate))

Time duration between two dates

i need to get the time duration in (hh:mm:ss) format between the two dates
2011/05/05 11:45:02 and 2011/05/01 08:09:57
For example if I had these two dates 2011/05/05 01:18:14 and 2011/05/05 11:00:00, the result would be: 02:18:14
DECLARE #dt1 datetime
DECLARE #dt2 datetime
SELECT #dt1 = '2011-05-05 11:45:02', #dt2 = '2011-05-05 08:09:57'
SELECT CONVERT(VARCHAR(8),#dt1-#dt2,108)
-- RESULT IS : 03:35:05
As far as i know there is no DATETIME_INTERVAL Data type in SQL (or TSQL) , so the only way you have to accomplish this is to manually format the result of a DATEDIFF function.
declare #hours as int
declare #minutes as int
declare #seconds as int
declare #time_interval as nvarchar(10)
set #hours = DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') / 3600
set #minutes = (DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') - #hours*3600)/60
set #seconds = DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') - #hours*3600 - #minutes * 60
set #time_interval = (cast(#hours as nvarchar) +':'+ cast(#minutes as nvarchar)+':'+ cast(#seconds as nvarchar))
print #time_interval
Try this:
declare #date1 datetime='2011/05/05 01:18:14', #date2 datetime='2011/05/05 11:00:00'
select CAST((#date2-#date1) as time(0))
Here is important order of elements in statement.In other case you will get 24h-your time.