I am trying to get the time format difference of two different times in firebird sql. I tried subtracting the two times but the result is not in time format.
TIME_IN TIME,
TIME_OUT TIME,
DIFFERENCE TIME
SELECT
TIME_IN,
TIME_OUT,
TIME_OUT - TIME_IN
Sample Data
TIME_IN = 7:00
TIME_OUT = 12:00
12:00 - 7:00
my expected output is 5:00
also tried using DATEDIFF but my result is not in time format
DATEDIFF (HOUR, TIME_IN, TIME_OUT)
Something like this:
SELECT
CAST(DATEDIFF(HOUR, CAST(EXTRACT(HOUR FROM CAST(CAST(:TIME_IN as varchar(5)) as time)) || ':00' as TIME), CAST(EXTRACT(HOUR FROM CAST(CAST(:TIME_OUT as varchar(5)) as time)) || ':00' as TIME))
|| ':' ||
DATEDIFF(MINUTE, CAST('00:' || EXTRACT(MINUTE FROM CAST(CAST(:TIME_IN as varchar(5))as time)) as TIME), CAST('00:' || EXTRACT(MINUTE FROM CAST(CAST(:TIME_OUT as varchar(5)) as time)) as TIME)) as TIME)
FROM sth
The result of DATEDIFF is an integral value for the specified type. So the result of DATEDIFF(HOUR, '07:00', '12:00') is 5, and not 5:00.
The SQL TIME datatype is only for a 24 hour time within a day, it is not for measuring duration.
If for some reason you want to format it as a time, you will need to do that yourself. For example, by taking the difference in minutes, and then calculating the correct representation in hours and minutes.
Related
I'm struggling with something that seems very obvious on first sight and most probably I'm overlooking something stupid but anyway.
I need to calculate the difference between timestamp fields and convert the result (which is as I assume a timestamp ) into the number of days and the elapsed time.
I can't seem to get the cast(xx to time) wright
I made a small example
SELECT
Cast(Cast( c_date AS CHAR(10)) || ' ' || Cast( c_time AS CHAR(10)) AS TIMESTAMP(6)) AS starttime ,
Cast(Cast( e_date AS CHAR(10)) || ' ' || Cast( e_time AS CHAR(10)) AS TIMESTAMP(6)) AS endtm,
(endtm - starttime) DAY(4) TO SECOND AS difftime
,Extract(DAY From difftime) --> gives the days
,Cast(difftime AS TIME)
,Extract (HOUR From difftime)
FROM (
SELECT Cast(Current_Timestamp AS DATE) c_date,
Cast(Current_Timestamp(0) AS TIME(0)) c_time,
Cast(Current_Timestamp + Random(1,10) * INTERVAL '1' DAY AS DATE) e_date,
Cast(Current_Timestamp(0) + Random(1,24) * INTERVAL '1' HOUR + Random(1,60) * INTERVAL '1' MINUTE AS TIME(0)) e_time
) t
,Cast(difftime AS TIME) gives me the trouble
the extract day and hour works => the difftime is really a timestamp (is it ? and if not what kind of field is it then ? ).
some advise would be nice :-)
I'm looking for some help in Oracle SQL. I need to query date and time in the where clause to find shift data based on current date. There are 3 shifts, 5am to 1pm, 1pm to 9pm and 9pm to 5am(next day morning. For example
SELECT 'T1' AS SHIFT, WORK_CENTER, SUM(CASE WHEN AQL='PASS' THEN 1 ELSE 0) END AS AQL_PASSED
FROM Z_INSPECTION_DEFECTS
WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH:MI:SS '') AND
DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 1:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH:MI:SS '')
I do not get any results from this query. The date time field is a timestamp on local Los Angeles time.
The immediate problem is that you're looking dor times that are after 5am and before 1am, which logically means nothing matches - as no time can fulfil both at once. You can use 24-hour times instead:
WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH24:MI:SS '') AND
DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), ''13:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH24:MI:SS '')
But there are other ways to get those, e.g. just without the queries against dual:
WHERE DATE_TIME >= TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || '' 5:00:00 '', ''DD-MON-YYYY HH24:MI:SS '') AND
DATE_TIME < TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || ''13:00:00 '', ''DD-MON-YYYY HH24:MI:SS '')
or with truncation and date arithmetic:
WHERE DATE_TIME >= TRUNC(CURRENT_DATE) + (5/24) AND
DATE_TIME < TRUNC(CURRENT_DATE) + (13/24)
You really need to be getting those times in the target time zone though, e.g.:
WHERE DATE_TIME >= FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), ''America/Los_Angeles'') AND
DATE_TIME < FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), ''America/Los_Angeles'')
You need to be careful with current_date, which is in you current session time zone, and sysdate which is in the server time zone. If your session is UTC then current_date might not give you the day you expect.
(I've stuck with escaped single quotes as that is mostly what you have in the question, implying you're probably running this with dynamic SQL; whether you need to is another matter. If you're only doing that to provide the period offsets at runtime then that wouldn't need to be dynamic...)
You can see the generated times from those calculations with:
select FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), 'America/Los_Angeles'),
FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), 'America/Los_Angeles')
from dual;
FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(5/24)ASTIMESTAM FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(13/24)ASTIMESTA
------------------------------------------------- -------------------------------------------------
2018-10-22 05:00:00.000000000 AMERICA/LOS_ANGELES 2018-10-22 13:00:00.000000000 AMERICA/LOS_ANGELES
I'm open to any suggestions, so long as I get something resembling the output at the bottom of the post, TIA!
Can I get some help with this sql fiddle: http://sqlfiddle.com/#!4/c51c5/1
SCHEMA
create table history(
clockingGroup varchar2(5)
, startTime timestamp
, endTime timestamp);
insert into history
(clockingGroup, startTime, endTime)
values
('grp1', '01-dec-2015 1:00:00.000000', '01-dec-2015 1:10:10.000000');
insert into history
(clockingGroup, startTime, endTime)
values
('grp2', '01-dec-2015 1:10:10.000000', '01-dec-2015 1:20:20.000000');
insert into history
(clockingGroup, startTime, endTime)
values
('grp1', '01-dec-2015 1:20:20.000000', '01-dec-2015 1:30:35.000000');
insert into history
(clockingGroup, startTime, endTime)
values
('grp3', '01-dec-2015 1:30:35.000000', '01-dec-2015 1:35:00.000000');
SQL
select
extract(hour from (sum(cast(endTime as date) - cast(startTime as date)))) || ' Hours '
|| extract(minute from (sum(cast(endTime as date) - cast(startTime as date)))) || ' Minutes '
|| extract(second from (sum(cast(endTime as date) - cast(startTime as date)))) || ' Seconds'
as totalTime
, clockingGroup
from
history
group by
clockingGroup
Current Error
ORA-30076: invalid extract field for extract source
My desired output is:
clockingGroup | totalTime
grp1 | 0 Hours 20 Minutes 25 Seconds
grp2 | 0 Hours 10 Minutes 10 Seconds
grp3 | 0 Hours 4 Minutes 25 Seconds
You are using the built ins in the wrong order. Your original query casts your timestamps to dates. When you subtract dates from each other you get a number.
In the query below it subtracts a timestamp from a timestamp which yields an INTERVAL. You cannot extract the hour from a number but you can from an INTERVAL.
SELECT clockingGroup.
SUM(extract(DAY FROM endtime-starttime)) ||' '||
SUM(extract(HOUR FROM endtime-starttime)) ||' '||
SUM(extract(MINUTE FROM endtime-starttime)) ||' '||
SUM(extract(SECOND FROM endtime-starttime)) AS TOTALTIME,
from
history
group by
clockingGroup
I see you have added another method using numtodsinterval. You are still converting timestamps to dates which you don't need to do if you want precision.
This query is more complicated as I try and show how you take the difference and count all the intervals as seconds, sum them and then break it apart into hours/minutes/seconds
SELECT CLOCKINGGROUP, TO_CHAR(TRUNC(SUMTOTALSECONDS/3600),'FM9900') || ' Hours ' ||
TO_CHAR(TRUNC(MOD(SUMTOTALSECONDS,3600)/60),'FM00') || ' Minutes ' ||
TO_CHAR(MOD(SUMTOTALSECONDS,60),'FM00') || ' Seconds'
FROM(
SELECT clockinggroup, TRUNC(SUM(TOTALSECONDS),0) AS SUMTOTALSECONDS
FROM (
SELECT clockinggroup,
EXTRACT (DAY FROM (EndTime-StartTime))*24*60*60 +
EXTRACT (HOUR FROM (EndTime-StartTime))*60*60 +
EXTRACT (MINUTE FROM (EndTime-StartTime))*60 +
EXTRACT (SECOND FROM (EndTime-StartTime))/60 AS TOTALSECONDS
FROM history)
group by
clockingGroup)
ORDER BY 1;
My table:
timestamp | value
------------------------+---------
2013-08-31 22:00:01.000 | 19.1
2013-08-31 22:00:03.000 | 21.5
...
Due to missing seconds in my data series i want to calculate an average value per minute. So instead of having a data series in seconds I want to have it in minutes instead, like so:
timestamp | value
-----------------+---------
2013-08-31 22:00 | 19.5
2013-08-31 22:01 | 21.1
...
How could I write an SQL query that give me this result? I am using SQL Server 2012.
Casting from datetime to smalldatetime avoids tedious (and computationally slow) mucking about with date-to-character-back-to-date conversions. The following will calculate the average per minute.
SELECT
cast(Timestamp as smalldatetime) Timestamp
,avg(value) Value
from PageLogs
group by cast(Timestamp as smalldatetime)
order by cast(Timestamp as smalldatetime)
The downsides is rounding; this would convert values between 21:00:30.000 and 22:01:29.997 to 22:00. If you need to average by "calendar" minutes (22:00:00.000 to 22:00:59.997), you'd have to adjust the times (at the millisecond level) to get the right breakpoints, like so:
SELECT
cast(dateadd(ms, -30000, Timestamp) as smalldatetime) Timestamp
,avg(value) Value
from PageLogs
group by cast(dateadd(ms, -30000, Timestamp) as smalldatetime)
order by cast(dateadd(ms, -30000, Timestamp) as smalldatetime)
You can remove seconds using CONVERT() with format 100:
SELECT CONVERT(VARCHAR,GETDATE(),100) AS Dt
,AVG(value)
FROM YourTable
GROUP BY CONVERT(VARCHAR,GETDATE(),100)
You could re-cast as DATETIME() if needed:
CAST(CONVERT(VARCHAR,GETDATE(),100)AS DATETIME)
That has seconds/miliseconds but they are all zeroes.
Goat CO's answer will work, but if you need the exact date format in your example you need to construct it manually:
select
convert(varchar, datepart(year, ts)) + '-' +
convert(varchar, datepart(month, ts)) + '-' +
convert(varchar, datepart(day, ts)) + ' ' +
convert(varchar, datepart(hour, ts)) + ':' +
convert(varchar, datepart(minute, ts)) as timestamp,
avg(value) as value
from
tbl
group by
datepart(year, ts),
datepart(month, ts),
datepart(day, ts),
datepart(hour, ts),
datepart(minute, ts)
I have this query
select CONVERT(varchar(5), tdate ,108) AS [Time] from table
which gives me the time in 24 hour format( military)
I wanted to convert it into a 12 hour format so i tried the query below
select SUBSTRING(CONVERT(VARCHAR, tdate, 100),13,2) + ':'
+ SUBSTRING(CONVERT(VARCHAR, tdate, 100),16,2) + ''
+ SUBSTRING(CONVERT(VARCHAR, tdate, 100),18,2) AS T
from table
and i get the 12 hour format but I am just curious if there is a shorter or better way of doing it. any help?
If you want to convert the current datetime for example:
SELECT CONVERT(VARCHAR, getdate(), 100) AS DateTime_In_12h_Format
Instead of getdate() you can put your desired column in a query (such as tdate in your example). If you want JUST the time in 12h and not the date and time use substring/right to separate them. It seems that you already know how to =).
This page lists every datetime conversion. It's really handy if you need other types of conversions.
This will return just the time, not the date.
SELECT RIGHT(CONVERT(VARCHAR, getdate(), 100), 7) AS time
For your table data:
select RIGHT(CONVERT(varchar, tdate ,100), 7) AS [Time] from table
Below code will return only time like 10:30 PM
SELECT FORMAT(CAST(getdate() AS DATETIME),'hh:mm tt') AS [Time]
Get date of server
SELECT LTRIM(RIGHT(CONVERT(VARCHAR(20), GETDATE(), 100), 7))
or
If it is stored in the table
SELECT LTRIM(RIGHT(CONVERT(VARCHAR(20), datename, 100), 7))
Result:
11:41AM
ifnull(date_format(at.date_time,'%d/%m/%Y'),"") AS date_time,
ifnull(time_format(at.date_time ,'%h:%i:%s'),"") AS date_time
This is how a SQL procedure looks...(for separating date and time)..there is no need of a special column for time/date....
Note:if H instead of h it will show the "hour in 24 hour" format