I am using the below to determine the minute between two times,
DateDiff(Minute, [MondayOpenTime] , [MondayCloseTime])
For a start time of 09:00 and a Close time of 17:30 it returns the value 510
Or if i use:
DateDiff(hour, [MondayOpenTime] , [MondayCloseTime])
It returns 8,
How do i get it to return the hours and minutes like 08:30
Using the minute, and then divide by 60, gives 8.5,
Note. I have been through many of the similar questions to this, if there is one with an exact answer i will delete this, but i cannot find any answers as of yet
You can calculate the hours by division as you stated. You can then use modulo to calculate the minutes.
declare #MondayOpenTime time = '09:00'
, #MondayCloseTime time = '17:30'
select convert(varchar(2), DateDiff(Minute, #MondayOpenTime , #MondayCloseTime) / 60) + ':' + right('0' + convert(varchar(2), DateDiff(Minute, #MondayOpenTime , #MondayCloseTime) % 60), 2)
For datetime(2) datatypes, the following could be used:
format([MondayCloseTime] - [MondayOpenTime], 'HH:mm')
Provided that the dates fall on the same day. (since these are opening times, that shouldn't be a problem)
As Sean pointed out: for time datatypes, subtraction isn't directly possible and an extra cast is needed:
format(cast([MondayCloseTime] as datetime) - cast([MondayOpenTime] as datetime), 'HH:mm')
(sidenote: format is only available on sql-server 2012 and higher)
Related
This is my code
concat(CONVERT(varchar(10), cast(cast(cast(DATE1 as int) as char(8)) as date), 101),
Above part is creating date format and then concatenating below with:
', ',
convert(varchar(5), (convert(time, left(RIGHT('000000' + CONVERT(varchar(6), TIME1), 6), 2)
+ ':' + substring(RIGHT('000000' + CONVERT(varchar(6), TIME1), 6), 3, 2)
+ ':' + substring(RIGHT('000000' + CONVERT(varchar(6), TIME1), 6), 5, 2))), 108))
This returns the time.
Combining the two in same line outputs as mm/dd/yyy, 13:00
I am converting original fields where date is written as yyyymmdd and time is written as 5-6 digits, 71200 (7:12, but seconds always 00).
This takes significantly long, so I would like a way to make the code more efficient.
A note, I am concatenating date with 4 different time columns, so maybe that's why it is taking long?
Try using DATEADD instead of string manipulations:
DATEADD(MINUTE, TIME1%10000/100,
DATEADD(HOUR,TIME1/10000,
CAST(CAST(CAST(DATE1 as int) AS char(8)) AS datetime))
TIME1 / 10000 should give you the number of hours. 71200 -> 7
TIME1 % 10000 should give you the number of minutes * 100. 71200 -> 1200
TIME1 % 10000 / 100 will give you the number of minutes. 71200 -> 12
If you are querying this data often (more often than you are inserting/updating it), or you care more about query performance than updating/insert performance, then you should consider making a persisted computed column on this table so that you don't have to do these calculations at query time. You can then also index the column which will help immensely if you regularly filter based on the datetime.
I have a number of hours which I need to display in the format of days and hours.
This number is derived from a DATEDIFF instruction.
For numbers less than 24, I wish to display only hours - ie, 21 hours.
For larger numbers, I wish to display days and hours - ie, 3 days, 14 hours
I do not need to display any smaller unit than hours, and values should be rounded down to the preceding hour, so 1 hour and 59 minutes will be 1 hour.
I cannot use a stored procedure - this must run as a single select statement.
I am aware that I can calculate the value by using modulo, so assuming 71 hours:
select concat((71 - (71 % 24)) / 24, ' days, ', 71 % 24, ' hours')
This however is somewhat messy, and as the statement must be a single select, I will have to calculate the DATEDIFF 3 times as below.
SELECT CONCAT (
(DATEDIFF(HOUR, StartDate, EndDate) -
(DATEDIFF(HOUR, StartDate, EndDate) % 24)) / 24,
' days, ',
DATEDIFF(HOUR, StartDate, EndDate) % 24,
' hours')
FROM RecordsTable
Is it possible to either format a number of hours as days and hours directly using an inbuilt SQL command, or failing that, select (datediff(hour, StartDate, EndDate) into a variable which I can reuse in the single select?
EDIT - As suggested, the solution was to use a CTE as follows:
WITH totalhours (htotal) AS
(
SELECT
DATEDIFF(HOUR, StartDate, EndDate) AS htotal
FROM
RecordsTable
)
SELECT
CONCAT ((htotal - (htotal % 24)) / 24,
' days, ',
htotal % 24,
' hours')
FROM
RecordsTable;
Use a CTE to generate your total once, and reference that total in your select against the CTE. Or use a subquery to generate the total once and then select from the subquery to get the desired results.
The fundamental issue is you need to materialize the total once to be able to reference it; forcing the engine to materialize a value is generally done via a CTE or subquery.
You can do a lot with datetime objects and format strings or datepart. For example,
declare #n int = 105;
select format(dateadd(day, -1, dateadd(hour, #n, '1753-1-1')), 'd h');
-- 4 9
Taking the minimum datetime value (1753-01-01), adding the requisite number of hours, subtracting one day (because on the first day you want days = 0), and then formatting.
You could improve the formatting like this:
select format(dateadd(day, -1, dateadd(hour, #n, '1753-1-1')), 'd \da\y(\s), h \hour(\s)');
-- 4 day(s), 9 hour(s)
Of course this will only work up to 31 days, because then you'll be out of the month of January in 1753 and into February. If that's the case, revert to datepart. This is uglier, but will work for larger values
select
datepart(day, (dateadd(day, -1, dateadd(hour, #n, '1753-1-1')))),
datepart(hour, (dateadd(day, -1, dateadd(hour, #n, '1753-1-1'))));
I have a Login/Logout system that compute the total hours work of the employees. My problem is the formatting of the date&time difference for minutes.
Example:
if user logged-in 8:00 AM and logged-out 6:30 PM, the total should be 10.50 but my SQL output is 10 hrs and 30 mins. I know the formula(it should be 30mins/60 = 50) but I didn't know where should I put that Dividend(/60) on my SQL Query.(see below my SQL Code).
SQL Code:
SELECT *,CAST(Datediff(HOUR, 0, logout_time - login_time) +
Cast(Datediff(MINUTE, 0, logout_time - login_time) -
(Datediff(HOUR, 0, logout_time - login_time) * 60 ) AS DECIMAL) / 100 AS Decimal(18,2)) AS [TotalHrs_Worked]
FROM table_DTR
WHERE CONVERT(VARCHAR(10),log_date, 101) BETWEEN '09/01/2014' AND '11/30/2014'
If you simply take the minutes between a pair of datetime values and multiply it by 60.0 (with a decimal place so it produces a result with a decimal value), this should work without problem:
Run this example:
DECLARE #start DATETIME = '2014-12-15 08:00:00'
DECLARE #end DATETIME = '2014-12-15 18:30:00'
SELECT DATEDIFF(minute, #start, #end)/60.0 AS HoursWorked
This will produce:
10.50
You shouldn't need to break it down in to minutes and hours like you are doing in your SQL.
I am running a query to find out the total amount of time a user has been browsing for. Each browsing session is stored in the DB as seconds and I then sum the total seconds and convert it into hh:mm:ss. The problem is when I'm converting the seconds into hh:mm:ss. I want it to display for example '78:20:00' but I dont know how to get the code to total it like this. When it gets past 24 hrs the hrs column goes back to 00 because its into a day.
The query I run to convert the time can be seen below:
SELECT Username,
CONVERT(VARCHAR(12),DATEADD(SECOND,TotalTimeInSeconds,0),108) AS TotalHours
FROM #TotalSessionTime
SELECT USERNAME,
CAST(TotalTimeInSeconds / (60 * 60) AS Varchar) + ':' +
CAST(TotalTimeInSeconds % (60 * 60) / 60 AS Varchar) + ':' +
CAST(TotalTimeInSeconds % (60) AS Varchar) AS TotalHours
FROM #TotalSessionTime
If you want minutes and seconds to always be two digits, you'll have to left pad them, which would make for an ugly example, but would work fine.
Try this...
DECLARE #TimeInSeconds int = 123400;
DECLARE #MyDate datetime;
SELECT #MyDate = CONVERT( DateTime, DATEADD( SECOND, #TimeInSeconds, 0))
SELECT CONVERT(CHAR(2), (DAY( #MyDate )-1) * 24 + DATEPART(hour,#MyDate)) + ':' + CONVERT(CHAR(2), DATEPART(minute, #MyDate)) + ':' + CONVERT(CHAR(2), DATEPART(SECOND, #MyDate))
You'll want to left-pad the minutes and seconds with a zero to be sure it's 2-digits, though.
I have to calculate the difference in hours (decimal type) between two dates in SQL Server 2008.
I couldn't find any useful technique to convert datetime to decimal with 'CONVERT' on MSDN.
Can anybody help me with that?
UPDATE:
To be clear, I need the fractional part as well (thus decimal type). So from 9:00 to 10:30 it should return me 1.5.
DATEDIFF(hour, start_date, end_date) will give you the number of hour boundaries crossed between start_date and end_date.
If you need the number of fractional hours, you can use DATEDIFF at a higher resolution and divide the result:
DATEDIFF(second, start_date, end_date) / 3600.0
The documentation for DATEDIFF is available on MSDN:
http://msdn.microsoft.com/en-us/library/ms189794%28SQL.105%29.aspx
Just subtract the two datetime values and multiply by 24:
Select Cast((#DateTime2 - #DateTime1) as Float) * 24.0
a test script might be:
Declare #Dt1 dateTime Set #Dt1 = '12 Jan 2009 11:34:12'
Declare #Dt2 dateTime Set #Dt2 = getdate()
Select Cast((#Dt2 - #Dt1) as Float) * 24.0
This works because all datetimes are stored internally as a pair of integers, the first integer is the number of days since 1 Jan 1900, and the second integer (representing the time) is the number of (1) ticks since Midnight. (For SmallDatetimes the time portion integer is the number of minutes since midnight). Any arithmetic done on the values uses the time portion as a fraction of a day. 6am = 0.25, noon = 0.5, etc... See MSDN link here for more details.
So Cast((#Dt2 - #Dt1) as Float) gives you total days between two datetimes. Multiply by 24 to convert to hours. If you need total minutes, Multiple by Minutes per day (24 * 60 = 1440) instead of 24...
NOTE 1: This is not the same as a dotNet or javaScript tick - this tick is about 3.33 milliseconds.
DATEDIFF but note it returns an integer so if you need fractions of hours use something like this:-
CAST(DATEDIFF(ss, startDate, endDate) AS decimal(precision, scale)) / 3600
Using Postgres I had issues with DATEDIFF, but had success with this:
DATE_PART('day',(delivery_time)::timestamp - (placed_time)::timestamp) * 24 +
DATE_PART('hour',(delivery_time)::timestamp - (placed_time)::timestamp) +
DATE_PART('minute',(delivery_time)::timestamp - (placed_time)::timestamp) / 60
which gave me an output like "14.3"
You are probably looking for the DATEDIFF function.
DATEDIFF ( datepart , startdate , enddate )
Where you code might look like this:
DATEDIFF ( hh , startdate , enddate )
DATEDIFF(minute,startdate,enddate)/60.0)
Or use this for 2 decimal places:
CAST(DATEDIFF(minute,startdate,enddate)/60.0 as decimal(18,2))
Declare #date1 datetime
Declare #date2 datetime
Set #date1 = '11/20/2009 11:00:00 AM'
Set #date2 = '11/20/2009 12:00:00 PM'
Select Cast(DateDiff(hh, #date1, #date2) as decimal(3,2)) as HoursApart
Result = 1.00
SELECT DATEDIFF(hh, firstDate, secondDate)
FROM tableName
WHERE ...