Update datetime fields date only - sql

Years ago a conversion from MSSQL 6.5 to MSSQL 2000 has been done and they realized just this week that the conversion failed to convert some datetime columns. It is now my task to fix that and I've been scratching my head on how I could preserve some pieces of information I know is accurate. Here is the structure of one of the table I need to fix.
DateTimeField1 DateTimeField2 DateTimeField3
01/01/1900 5:50:00 PM 01/01/1900 5:52:00 PM 15/02/2005 12:00:00 AM
This is one sample of the many records that are corrupted, unfortunatly I don't have access of any backup from before the conversion. As you can see, the date part is the default value for a DateTime field and is the part I need to fix. I have the following select, which gives me the rows I need to fix.
SELECT DateTimeField1, DateTimeField2, DateTimeField3
FROM Table1
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101')
Now assume I have 60 records resulting from the select. I need to update those records based on the DateTimeField3 DATE part only. The sample above would look like;
DateTimeField1 DateTimeField2 DateTimeField3
15/02/2005 5:50:00 PM 15/02/2005 5:52:00 PM 15/02/2005 12:00:00 AM
Any idea on how to achieve this?

If one field is always 1900-01-01 but with the correct time, and the other field is 12:00:00 AM but with the correct date, you can just add them together.
UPDATE Test
SET
DateTimeField1 = DateTimeField1 + DateTimeField3,
DateTimeField2 = DateTimeField2 + DateTimeField3
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101')
See this SQL Fiddle.
1900-01-01 is the "zero" date, so if you add it to something else, you get that same value. 12:00:00 AM is the "zero" time.
If there are cases where DateTimeField1 has the correct date but DateTimeField2 doesn't, you might want to do this as two separate queries.

I believe you want to only update DateTimeField1 & DateTimeField2 when they are less than '20000101'. CASE Statement will take care of not updating wrong field.
Try single query UPDATE -
SQL SERVER 2008 AND LATER -
UPDATE Table1
SET DateTimeField1 = (CASE WHEN (DateTimeField1 < '20000101')
THEN CAST(CAST (DateTimeField3 AS DATE) AS DATETIME)
+ CAST (DateTimeField1 AS TIME)
ELSE DateTimeField1
END)
, DateTimeField2 = (CASE WHEN (DateTimeField2 < '20000101')
THEN CAST(CAST (DateTimeField3 AS DATE) AS DATETIME)
+ CAST (DateTimeField2 AS TIME)
ELSE DateTimeField2
END)
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101');
EARLIER THAN SQL SERVER 2008 -
UPDATE Table1
SET DateTimeField1 = (CASE WHEN (DateTimeField1 < '20000101')
THEN DATEADD(DAY, 0, DATEDIFF(day, 0, DateTimeField3))
+ DATEADD(DAY, 0 - DATEDIFF(day, 0, DateTimeField1), DateTimeField1)
ELSE DateTimeField1
END)
, DateTimeField2 = (CASE WHEN (DateTimeField2 < '20000101')
THEN DATEADD(DAY, 0, DATEDIFF(day, 0, DateTimeField3))
+ DATEADD(DAY, 0 - DATEDIFF(day, 0, DateTimeField2), DateTimeField2)
ELSE DateTimeField2
END)
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101');

Use this query:
SELECT DateTimeField1 =
convert(datetime,convert(int,convert(float,t.DateTimeField3))
+ convert(float,t.DateTimeField1)),
DateTimeField2 =
convert(datetime,convert(int,convert(float,t.DateTimeField3))
+ convert(float,t.DateTimeField2)),
FROM Table1 t
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101')
SQL Server stores datetime as a float, where a right side is a time and a left side is a date. This query replaces the left side of the wrong datetime by the left side of the correct datetime

Try something like this, it should work on MSSQL 2000
UPDATE tab SET DateTimeField1 =
ltrim(str(datepart(year, DateTimeField3))) + '-' +
ltrim(str(datepart(month, DateTimeField3))) + '-' +
ltrim(str(datepart(day, DateTimeField3))) + ' ' +
ltrim(str(datepart(hour, DateTimeField1))) + ':' +
ltrim(str(datepart(minute, DateTimeField1))) + ':' +
ltrim(str(datepart(second, DateTimeField1))) + '.' +
ltrim(str(datepart(millisecond, DateTimeField1))) ,
DateTimeField2 = ltrim(str(datepart(year, DateTimeField3))) + '-' +
ltrim(str(datepart(month, DateTimeField3))) + '-' +
ltrim(str(datepart(day, DateTimeField3))) + ' ' +
ltrim(str(datepart(hour, DateTimeField2))) + ':' +
ltrim(str(datepart(minute, DateTimeField2))) + ':' +
ltrim(str(datepart(second, DateTimeField2))) + '.' +
ltrim(str(datepart(millisecond, DateTimeField2)))
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101')

This should do what you need:
update <yourtable>
set
DateTimeField1 = case when cast('1 jan 1900' as datetime) = cast(floor(cast(DateTimeField1 as float)) as datetime) then DateTimeField1 + DateTimeField3 else date1 end,
DateTimeField2 = case when cast('1 jan 1900' as datetime) = cast(floor(cast(DateTimeField2 as float)) as datetime) then DateTimeField2 + DateTimeField3 else date2 end
where DateTimeField1 < '2 jan 1900' or DateTimeField2 < '2 jan 1900'
This works by checking to see if the date and time, converted to a float and then floored (which removes the time part) equals 1st Jan 1900.
As the date part of DateTimeField1 or DateTimeField2 are essentially 0 and the time part of DateTimeField3 is 0, you can simply add the two together.

The simplest way to do this would be:
update Table1
set
DateTimeField1 = cast(cast(DateTimeField1 as float)-floor(cast(DateTimeField1 as float)) + floor(cast(DateTimeField3 as float)) as datetime
WHERE DateTimeField1 < '20000101'
update Table1
set
DateTimeField2 = cast(cast(DateTimeField2 as float)-floor(cast(DateTimeField2 as float)) + floor(cast(DateTimeField3 as float)) as datetime
WHERE DateTimeField2 < '20000101'
I know it'd work for SQL Server 2005 and 2008, but I'm not sure about 2000 edition, so test this first.
The explanation is this: datetime is stored as float value, where int part is date, and decimal part is time. So by floor(cast(DateTimeField3 as float)) you get date part, and you can simply add this to DateTimeField1 and DateTimeField2, after you subtracted date part from them.
For 1900-01-01 date part would be zero: select cast(0 as datetime), but it'll still work.

Related

Construct a date from parts in SQL Server 2008

I am using SQL Server 2008 and trying to form a query that will use a CASEstatement with a date calculation to return one of two dates depending on what day of the month the calculation results in.
The goal is if the calculation (in query below) CURRENT_TIMESTAMP + LEAD_TIME results in a day between the 1st and 15th, then assign the 15th of that month. Otherwise, return the last day of that month.
For example, if CURRENT_TIMESTAMP + LEAD_TIME = 07/12/19, return 07/15/19. If that calculation = 07/16/19, return 07/31/19.
This seems like it would be possible using DATEFROMPARTS but I believe since I am using SQL Server 2008 that function is not defined (that is the error I am returning). Any ideas on a work around?
SQL:
SELECT I.po_number,
I.po_item_number AS 'po_item',
S.orderentry_date,
I.po_req_ship_date,
I.ex_factory_date,
I.del_indicator,
H.po_type,
H.vendor_no,
CASE WHEN DATEPART(dd,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)) BETWEEN 1 AND 15
THEN DATEFROMPARTS(DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),15)
ELSE DATEFROMPARTS(DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME),mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)+1,0))
END AS 'LT_CALC',
H.po_created_by,
I.comment
FROM rbk_sap_user..vw_po_header H
JOIN rbk_sap_user..vw_po_item I ON H.po_number = I.po_number
JOIN rbk_sap_user..vw_mm_material MM ON I.material = MM.material
JOIN (SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder1
UNION ALL
SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder2
UNION ALL
SELECT order_no,
orderentry_date
FROM asagdwpdx_prod..SimoxOrder3
) S ON S.order_no = H.ahag_number
WHERE S.orderentry_date BETWEEN '01/31/2019' AND '02/13/2019'
AND I.del_indicator <> 'L'
AND H.po_type NOT IN ('02','06','10','UB')
AND MM.business_segment_code NOT IN ('420','421','422','424')
You can convert all the parts of the date to VARCHAR and string them together to yyyy-mm-dd format, and then CONVERT toDATETIME.
SELECT
...
CASE WHEN DATEPART(dd,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)) BETWEEN 1 AND 15
THEN CONVERT(DATETIME, CONVERT(varchar, DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)))+ '-' + CONVERT(VARCHAR, DATEPART (mm,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME))) + '-' + CONVERT(VARCHAR, 15))
ELSE DATEADD(DAY, -1, CONVERT(DATETIME, CONVERT(VARCHAR, DATEPART(yyyy,(CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)))+ '-' + CONVERT(VARCHAR, DATEPART(mm,CURRENT_TIMESTAMP + MM.IAM_MAN_LEAD_TIME)+ 1) + '-' + CONVERT(VARCHAR, 1)))
END AS 'LT_CALC'
...
Note that in the ELSE statement, the logic to get the last day of the month is to go the first day of the following month, and then use the DATEADD function to subtract one day. The SQL Server function EOMONTH , introduced in SQL Server 2012, eliminates the need for that logic.
Try this
SELECT CAST(LEFT(CONVERT(varchar, CURRENT_TIMESTAMP + LEAD_TIME, 103 ),2) as int)
then
CASE WHEN CAST(LEFT(CONVERT(varchar, CURRENT_TIMESTAMP + LEAD_TIME, 103 ),2) as int) < 15 THEN
....
ELSE
....
END

SQL Find/Ignore invalid date

I am using SQL Server.
From each row, I take day and month values from the fields c.daybirth,c.monthbirth
and the year from getdate(), and I want to have a field that shows if this date is valid or not (invalid example: 31 February)
I have created this solution:
case day(dateadd(month,c.monthbirth-1,dateadd(day,c.daybirth-1,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))) when c.daybirth then 1 else 0 end
which works, but I find it hard to read. Is there a smarter alternative?
In SQL Server 2012+, you can do:
where try_convert(date,
datefromparts(year(getdate()), c.monthbirth, c.daybirth)
) is not null
EDIT:
Amusing. This is better:
where try_convert(date,
cast(year(getdate()) * 10000 + c.monthbirth * 100 + c.daybirth as varchar(255))
) is not null

Difficulty in getting Shift Value in SQL Query

Currently my table structire for table SHIFT is as follow:
ID Name Start End
1 Shift1 06:00 14:00
2 Shift2 14:00 22:00
3 Shift3 22:00 06:00
Now I pass parameter to this query in hour like 11 or 15 or 22 or 03
For that parameter, I would like to get the result that in which shift the passed hour will reside.
So if I pass 11, it shoud give me Shift1. If I pass 23, it should give me Shift3.
Following query that I wrote works fine for any value from 07 to 21, it is giving me blank value and for obvious reasons.
select * from MII_SHIFT
where '[Param.1]' >= left(START,2) and '[Param.1]' < left(END,2)
Can anyone help me how can I change the query so that I can get proper response for 22,23,00,01,02,03,04,05.
Thanks
SELECT *
FROM shift
WHERE
( left(START,2) > left(END,2)
AND ('[Param.1]' >= left(START,2) OR '[Param.1]' < left(END,2))
)
OR ( left(START,2) < left(END,2)
AND '[Param.1]' >= left(START,2) AND '[Param.1]' < left(END,2)
)
I answer a similar answer a litle time ago.
Shorts start < end (5-9): the value need be between start and end
Jacket start > end (10-4): the value is < start or > end
Assuming the values are stored as strings, then this is pretty easy:
select s.*
from shifts s
where (start < end and right('00' + #param1, 2) >= start and right('00' + #param1, 2) < end) or
(start > end and (right('00' + #param1, 2) >= start or right('00' + #param1, 2) < end))
This assumes that #param1 is a string. The right() is used to left pad the string with zeroes. If that is already true, then the code would be even simpler.
EDIT:
With padding, this simplifies to:
select s.*
from shifts s
where (start < end and #param1 >= start and #param1< end) or
(start > end and (#param1 >= start or #param1 < end))
Simplest way is most likely to convert the times into dates, and if the end date is earlier than start, then add one day. You could use time datatype as input too, instead of just hour, but this is now an example with int:
declare #hour int, #date datetime
set #hour = 3
set #date = convert(datetime, convert(varchar(2), #hour) + ':00', 108)
select Name
from (
select Name,
[Start] as Start1,
case when [End] < [Start] then dateadd(day, 1, [End]) else [End] End as End1,
case when [End] < [Start] then dateadd(day, -1, [Start]) else [Start] End as Start2,
[End] as End2
from (
select Name, convert(datetime, [Start], 108) as [Start], convert(datetime, [End], 108) as [End]
from Table1
) X
) Y
where ((Start1 <= #date and #date < End1) or (Start2 <= #date and #date < End2))
Edit: added 2nd start / end columns to the derived table to handle second part of the shift.
Example in SQL Fiddle
Thankk you all. With the hep from all of your refrences, I was able to build the query which gave me appropriate results.
Query is as foolow:
SELECT Name FROM SHIFT WHERE
(LEFT(START,2) < LEFT(END,2) AND '[Param.1]' >= LEFT(START,2) AND '[Param.1]' < LEFT(END,2))
OR
(LEFT(START,2) > LEFT(END,2) AND ('[Param.1]' >= LEFT(START,2) OR '[Param.1]' < LEFT(END,2)))

SQL query for today's date minus two months

I want to select all the records in a table where their date of entry is older then 2 months.
Any idea how I can do that?
I haven't tried anything yet but I am on this point:
SELECT COUNT(1) FROM FB WHERE Dte > GETDATE()
If you are using SQL Server try this:
SELECT * FROM MyTable
WHERE MyDate < DATEADD(month, -2, GETDATE())
Based on your update it would be:
SELECT * FROM FB WHERE Dte < DATEADD(month, -2, GETDATE())
Would something like this work for you?
SELECT * FROM FB WHERE Dte >= DATE(NOW() - INTERVAL 2 MONTH);
TSQL, Alternative using variable declaration. (it might improve Query's readability)
DECLARE #gapPeriod DATETIME = DATEADD(MONTH,-2,GETDATE()); --Period:Last 2 months.
SELECT
*
FROM
FB as A
WHERE
A.Dte <= #gapPeriod; --only older records.
SELECT COUNT(1) FROM FB
WHERE Dte > DATE_SUB(now(), INTERVAL 2 MONTH)
I use this on SQL Server:
SELECT
DATEADD(MONTH,-2,GETDATE()) '- 2 months'
FROM MyTable
SELECT COUNT(1)
FROM FB
WHERE
Dte BETWEEN CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '-' + CAST(MONTH(DATEADD(month, -1, GETDATE())) AS VARCHAR(2)) + '-20 00:00:00'
AND CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '-' + CAST(MONTH(GETDATE()) AS VARCHAR(2)) + '-20 00:00:00'

Difference of two date time in sql server

Is there any way to take the difference between two datetime in sql server?
For example, my dates are
2010-01-22 15:29:55.090
2010-01-22 15:30:09.153
So, the result should be 14.063 seconds.
Just a caveat to add about DateDiff, it counts the number of times you pass the boundary you specify as your units, so is subject to problems if you are looking for a precise timespan.
e.g.
select datediff (m, '20100131', '20100201')
gives an answer of 1, because it crossed the boundary from January to February, so even though the span is 2 days, datediff would return a value of 1 - it crossed 1 date boundary.
select datediff(mi, '2010-01-22 15:29:55.090' , '2010-01-22 15:30:09.153')
Gives a value of 1, again, it passed the minute boundary once, so even though it is approx 14 seconds, it would be returned as a single minute when using Minutes as the units.
SELECT DATEDIFF (MyUnits, '2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')
Substitute "MyUnits" based on DATEDIFF on MSDN
SELECT DATEDIFF(day, '2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')
Replace day with other units you want to get the difference in, like second, minute etc.
I can mention four important functions of MS SQL Server that can be very useful:
1) The function DATEDIFF() is responsible to calculate differences between two dates, the result could be "year quarter month dayofyear day week hour minute second millisecond microsecond nanosecond", specified on the first parameter (datepart):
select datediff(day,'1997-10-07','2011-09-11')
2) You can use the function GETDATE() to get the actual time and calculate differences of some date and actual date:
select datediff(day,'1997-10-07', getdate() )
3) Another important function is DATEADD(), used to convert some value in datetime using the same datepart of the datediff, that you can add (with positive values) or substract (with negative values) to one base date:
select DATEADD(day, 45, getdate()) -- actual datetime adding 45 days
select DATEADD( s,-638, getdate()) -- actual datetime subtracting 10 minutes and 38 seconds
4) The function CONVERT() was made to format the date like you need, it is not parametric function, but you can use part of the result to format the result like you need:
select convert( char(8), getdate() , 8) -- part hh:mm:ss of actual datetime
select convert( varchar, getdate() , 112) -- yyyymmdd
select convert( char(10), getdate() , 20) -- yyyy-mm-dd limited by 10 characters
DATETIME cold be calculated in seconds and one interesting result mixing these four function is to show a formated difference um hours, minutes and seconds (hh:mm:ss) between two dates:
declare #date1 datetime, #date2 datetime
set #date1=DATEADD(s,-638,getdate())
set #date2=GETDATE()
select convert(char(8),dateadd(s,datediff(s,#date1,#date2),'1900-1-1'),8)
... the result is 00:10:38 (638s = 600s + 38s = 10 minutes and 38 seconds)
Another example:
select distinct convert(char(8),dateadd(s,datediff(s, CRDATE , GETDATE() ),'1900-1-1'),8) from sysobjects order by 1
I tried this way and it worked. I used SQL Server version 2016
SELECT DATEDIFF(MILLISECOND,'2010-01-22 15:29:55.090', '2010-01-22 15:30:09.153')/1000.00;
Different DATEDIFF Functions are:
SELECT DATEDIFF(year, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(quarter, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(month, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(dayofyear, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(day, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(hour, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(minute, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(second, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
SELECT DATEDIFF(millisecond, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
Ref: https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
Ok we all know the answer involves DATEDIFF(). But that gives you only half the result you may be after. What if you want to get the results in human-readable format, in terms of Minutes and Seconds between two DATETIME values?
The CONVERT(), DATEADD() and of course DATEDIFF() functions are perfect for a more easily readable result that your clients can use, instead of a number.
i.e.
CONVERT(varchar(5), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114)
This will give you something like:
HH:MM
If you want more precision, just increase the VARCHAR().
CONVERT(varchar(12), DATEADD(minute, DATEDIFF(MINUTE, date1, date2), 0), 114)
HH:MM.SS.MS
There are a number of ways to look at a date difference, and more when comparing date/times. Here's what I use to get the difference between two dates formatted as "HH:MM:SS":
ElapsedTime AS
RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
I used this for a calculated column, but you could trivially rewrite it as a UDF or query calculation. Note that this logic rounds down fractional seconds; 00:00.00 to 00:00.999 is considered zero seconds, and displayed as "00:00:00".
If you anticipate that periods may be more than a few days long, this code switches to D:HH:MM:SS format when needed:
ElapsedTime AS
CASE WHEN DATEDIFF(S, StartDate, EndDate) >= 359999
THEN
CAST(DATEDIFF(S, StartDate, EndDate) / 86400 AS VARCHAR(7)) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 86400 / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
ELSE
RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) / 3600 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 3600 / 60 AS VARCHAR(2)), 2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, StartDate, EndDate) % 60 AS VARCHAR(2)), 2)
END
The following query should give the exact stuff you are looking out for.
select datediff(second, '2010-01-22 15:29:55.090' , '2010-01-22 15:30:09.153')
Here is the link from MSDN for what all you can do with datediff function .
https://msdn.microsoft.com/en-us/library/ms189794.aspx
Internally in SQL Server dates are stored as 2 integers. The first integer is the number of days before or after the base date (1900/01/01). The second integer stores the number of clock ticks after midnight, each tick is 1/300 of a second.
More info here
Because of this, I often find the simplest way to compare dates is to simply substract them. This handles 90% of my use cases. E.g.,
select date1, date2, date2 - date1 as DifferenceInDays
from MyTable
...
When I need an answer in units other than days, I will use DateDiff.
SELECT DATEDIFF(yyyy, '2011/08/25', '2017/08/25') AS DateDiff
It's gives you difference between two dates in Year
Here (2017-2011)=6 as a result
Syntax:
DATEDIFF(interval, date1, date2)
Use This for DD:MM:SS:
SELECT CONVERT(VARCHAR(max), Datediff(dd, '2019-08-14 03:16:51.360',
'2019-08-15 05:45:37.610'))
+ ':'
+ CONVERT(CHAR(8), Dateadd(s, Datediff(s, '2019-08-14 03:16:51.360',
'2019-08-15 05:45:37.610'), '1900-1-1'), 8)
So this isn't my answer but I just found this while searching around online for a question like this as well. This guy set up a procedure to calculate hours, minutes and seconds. The link and the code:
--Creating Function
If OBJECT_ID('UFN_HourMinuteSecond') Is Not Null
Drop Function dbo.UFN_HourMinuteSecond
Go
Exec(
'Create Function dbo.UFN_HourMinuteSecond
(
#StartDateTime DateTime,
#EndDateTime DateTime
) Returns Varchar(10)
As
Begin
Declare #Seconds Int,
#Minute Int,
#Hour Int,
#Elapsed Varchar(10)
Select #Seconds = ABS(DateDiff(SECOND ,#StartDateTime,#EndDateTime))
If #Seconds >= 60
Begin
select #Minute = #Seconds/60
select #Seconds = #Seconds%60
If #Minute >= 60
begin
select #hour = #Minute/60
select #Minute = #Minute%60
end
Else
Goto Final
End
Final:
Select #Hour = Isnull(#Hour,0), #Minute = IsNull(#Minute,0), #Seconds = IsNull(#Seconds,0)
select #Elapsed = Cast(#Hour as Varchar) + '':'' + Cast(#Minute as Varchar) + '':'' + Cast(#Seconds as Varchar)
Return (#Elapsed)
End'
)
declare #dt1 datetime='2012/06/13 08:11:12', #dt2 datetime='2012/06/12 02:11:12'
select CAST((#dt2-#dt1) as time(0))
PRINT DATEDIFF(second,'2010-01-22 15:29:55.090','2010-01-22 15:30:09.153')
select
datediff(millisecond,'2010-01-22 15:29:55.090','2010-01-22 15:30:09.153') / 1000.0 as Secs
result:
Secs
14.063
Just thought I'd mention it.
Sol-1:
select
StartTime
, EndTime
, CONVERT(NVARCHAR,(EndTime-StartTime), 108) as TimeDiff
from
[YourTable]
Sol-2:
select
StartTime
, EndTime
, DATEDIFF(hh, StartTime, EndTime)
, DATEDIFF(mi, StartTime, EndTime) % 60
from
[YourTable]
Sol-3:
select
DATEPART(hour,[EndTime]-[StartTime])
, DATEPART(minute,[EndTime]-[StartTime])
from
[YourTable]
Datepart works the best
Please check below trick to find the date difference between two dates
DATEDIFF(DAY,ordr.DocDate,RDR1.U_ProgDate) datedifff
where you can change according your requirement as you want difference of days or month or year or time.
CREATE FUNCTION getDateDiffHours(#fdate AS datetime,#tdate as datetime)
RETURNS varchar (50)
AS
BEGIN
DECLARE #cnt int
DECLARE #cntDate datetime
DECLARE #dayDiff int
DECLARE #dayDiffWk int
DECLARE #hrsDiff decimal(18)
DECLARE #markerFDate datetime
DECLARE #markerTDate datetime
DECLARE #fTime int
DECLARE #tTime int
DECLARE #nfTime varchar(8)
DECLARE #ntTime varchar(8)
DECLARE #nfdate datetime
DECLARE #ntdate datetime
-------------------------------------
--DECLARE #fdate datetime
--DECLARE #tdate datetime
--SET #fdate = '2005-04-18 00:00:00.000'
--SET #tdate = '2005-08-26 15:06:07.030'
-------------------------------------
DECLARE #tempdate datetime
--setting weekends
SET #fdate = dbo.getVDate(#fdate)
SET #tdate = dbo.getVDate(#tdate)
--RETURN #fdate
SET #fTime = datepart(hh,#fdate)
SET #tTime = datepart(hh,#tdate)
--RETURN #fTime
if datediff(hour,#fdate, #tdate) <= 9
RETURN(convert(varchar(50),0) + ' Days ' + convert(varchar(50),datediff(hour,#fdate, #tdate))) + ' Hours'
else
--setting working hours
SET #nfTime = dbo.getV00(convert(varchar(2),datepart(hh,#fdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,#fdate))) + ':'+ dbo.getV00(convert(varchar(2),datepart(ss,#fdate)))
SET #ntTime = dbo.getV00(convert(varchar(2),datepart(hh,#tdate))) + ':' +dbo.getV00(convert(varchar(2),datepart(mi,#tdate))) + ':'+ dbo.getV00(convert(varchar(2),datepart(ss,#tdate)))
IF #fTime > 17
begin
set #nfTime = '17:00:00'
end
else
begin
IF #fTime < 8
set #nfTime = '08:00:00'
end
IF #tTime > 17
begin
set #ntTime = '17:00:00'
end
else
begin
IF #tTime < 8
set #ntTime = '08:00:00'
end
-- used for working out whole days
SET #nfdate = dateadd(day,1,#fdate)
SET #ntdate = #tdate
SET #nfdate = convert(varchar,datepart(yyyy,#nfdate)) + '-' + convert(varchar,datepart(mm,#nfdate)) + '-' + convert(varchar,datepart(dd,#nfdate))
SET #ntdate = convert(varchar,datepart(yyyy,#ntdate)) + '-' + convert(varchar,datepart(mm,#ntdate)) + '-' + convert(varchar,datepart(dd,#ntdate))
SET #cnt = 0
SET #dayDiff = 0
SET #cntDate = #nfdate
SET #dayDiffWk = convert(decimal(18,2),#ntdate-#nfdate)
--select #nfdate,#ntdate
WHILE #cnt < #dayDiffWk
BEGIN
IF (NOT DATENAME(dw, #cntDate) = 'Saturday') AND (NOT DATENAME(dw, #cntDate) = 'Sunday')
BEGIN
SET #dayDiff = #dayDiff + 1
END
SET #cntDate = dateadd(day,1,#cntDate)
SET #cnt = #cnt + 1
END
--SET #dayDiff = convert(decimal(18,2),#ntdate-#nfdate) --datediff(day,#nfdate,#ntdate)
--SELECT #dayDiff
set #fdate = convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) + ' ' + #nfTime
set #tdate = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate)) + ' ' + #ntTime
set #markerFDate = convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) + ' ' + '17:00:00'
set #markerTDate = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate)) + ' ' + '08:00:00'
--select #fdate,#tdate
--select #markerFDate,#markerTDate
set #hrsDiff = convert(decimal(18,2),datediff(hh,#fdate,#markerFDate))
--select #hrsDiff
set #hrsDiff = #hrsDiff + convert(int,datediff(hh,#markerTDate,#tdate))
--select #fdate,#tdate
IF convert(varchar,datepart(yyyy,#fdate)) + '-' + convert(varchar,datepart(mm,#fdate)) + '-' + convert(varchar,datepart(dd,#fdate)) = convert(varchar,datepart(yyyy,#tdate)) + '-' + convert(varchar,datepart(mm,#tdate)) + '-' + convert(varchar,datepart(dd,#tdate))
BEGIN
--SET #hrsDiff = #hrsDiff - 9
Set #hrsdiff = datediff(hour,#fdate,#tdate)
END
--select FLOOR((#hrsDiff / 9))
IF (#hrsDiff / 9) > 0
BEGIN
SET #dayDiff = #dayDiff + FLOOR(#hrsDiff / 9)
SET #hrsDiff = #hrsDiff - FLOOR(#hrsDiff / 9)*9
END
--select convert(varchar(50),#dayDiff) + ' Days ' + convert(varchar(50),#hrsDiff) + ' Hours'
RETURN(convert(varchar(50),#dayDiff) + ' Days ' + convert(varchar(50),#hrsDiff)) + ' Hours'
END
For Me This worked Perfectly
Convert(varchar(8),DATEADD(SECOND,DATEDIFF(SECOND,LogInTime,LogOutTime),0),114)
and the Output is
HH:MM:SS which is shown accurately in my case.
Please try
DECLARE #articleDT DATETIME;
DECLARE #nowDate DATETIME;
-- Time of the ARTICLE created
SET #articleDT = '2012-04-01 08:10:16';
-- Simulation of NOW datetime
-- (in real world you would probably use GETDATE())
SET #nowDate = '2012-04-10 11:35:36';
-- Created 9 days ago.
SELECT 'Created ' + CAST(DATEDIFF(day, #articleDT, #nowDate) AS NVARCHAR(50)) + ' days ago.';
-- Created 1 weeks, 2 days, 3 hours, 25 minutes and 20 seconds ago.
SELECT 'Created '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 / 24 / 7 AS NVARCHAR(50)) + ' weeks, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 / 24 % 7 AS NVARCHAR(50)) + ' days, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 / 60 % 24 AS NVARCHAR(50)) + ' hours, '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) / 60 % 60 AS NVARCHAR(50)) + ' minutes and '
+ CAST(DATEDIFF(second, #articleDT, #nowDate) % 60 AS NVARCHAR(50)) + ' seconds ago.';
For MS SQL, you can convert the datetime value to a double value.
The integer part contains the number of days since 1900-01-01, the fractional part contains the time in hours.
So you can calculate date difference as:
cast(date1-date2 as FLOAT)