aggregate function SUM for time values in MySQL - mysql

I'm trying to generate ranklist, in which I have to sum many time durations to get total time, when I tried SUM(TIMEDIFF(finishTime,'starttime')) in MySQL I noted that addition of two time durations occurs as if they were two normal numbers, ie if I add 00:00:50 and 00:00:50, I get 00:01:00 as answer.
TO_SECOND is not available in MySQL 5.1.

SUM(TIMEDIFF(TIME_TO_SEC(finishtime) - TIME_TO_SEC(starttime)));
Use TIME_TO_SEC to convert TIME to seconds for math operation

In the event that you were working with datetime timestamps, I found that I could get more reliable results using the following method:
SUM( UNIX_TIMESTAMP( finishtime ) - UNIX_TIMESTAMP( starttime ) ) /3600

Related

The difference between datetime data in SQL

how can i find the difference between two dateTime store in a MySQL database
e.g the difference in hours between 2016-03-09 04:30:00 and 2016-03-10 03:00:00.
i have tried dateDiff() but it does not compare the hours that is need to see the difference between (2016-03-09 04:30:00) - (2016-03-10 03:10:00).
the order is year-month-day time
The output i need is the number of hours between these times also considering the time as well.
You can use TIMESTAMPDIFF to find the difference between two timestamps
SELECT TIMESTAMPDIFF(HOUR,'2009-05-18 10:00','2009-05-18 11:00');
If you want fraction(eg: 1.5 hrs) hours you can do like below
SELECT (UNIX_TIMESTAMP('2012-10-30 10:40')-UNIX_TIMESTAMP('2012-10-30 10:30'))/3600 hour_diff
One simple method is to use to_seconds():
select to_seconds(dt1) - to_seconds(dt2)
This gives the difference in seconds. Then you can divide by 60*60 to get hours or 24*60*60 for days.

T-SQL Select data from multiple days between certain times

In my table I have minute data about daily temperature measurements. The table looks like:
DateTime timestamp, Float temperature
I would like to have the temperatures on different dates between a certain interval and then only show the temperature between 7am and 8pm.
I know how to get the data between dates:
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
How to I implement the time restriction (7am - 8pm) as well?
Thanks a lot!!
If you are on SQL Server 2008 or above, you can use TIME datatype
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND CONVERT(TIME,[timestamp]) BETWEEN '19:00:00' AND '20:00:00'
EDIT: Also it is recommended to use ISO (yyyymmdd) date format when using date as a string. i.e.
BETWEEN '20121110' and '20121117'
The DateTime and TimeStamp values should contain precision you need, so
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND RIGHT([timestamp], 12) BETWEEN '19:00:00.000' AND '20:00.00.000'
You may need to adjust how many characters you are evaluating in the RIGHT predicate depending on the precision in your database. But the idea is to take all the parts that constitute the hours, minutes, seconds and miliseconds and restrict that to just those between the hours you require.

How do I get the average time from a series of DateTime columns in SQL Server 2008?

Lets say I have a table that contains the following - id and date (just to keep things simple).
It contains numerous rows.
What would my select query look like to get the average TIME for those rows?
Thanks,
Disclaimer: There may be a much better way to do this.
Notes:
You can't use the AVG() function against a DATETIME/TIME
I am casting DATETIME to DECIMAL( 18, 6 ) which appears to yield a reasonably (+- few milliseconds) precise result.
#1 - Average Date
SELECT
CAST( AVG( CAST( TimeOfInterest AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
#2 - Average Time - Remove Date Portion, Cast, and then Average
SELECT
CAST( AVG( CAST( TimeOfInterest - CAST( TimeOfInterest AS DATE ) AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
The second example subtracts the date portion of the DATETIME from itself, leaving only the time portion, which is then cast to a decimal for averaging, and back to a DATETIME for formatting. You would need to strip out the date portion (it's meaningless) and the time portion should represent the average time in the set.
SELECT CAST(AVG(CAST(ReadingDate AS real) - FLOOR(CAST(ReadingDate as real))) AS datetime)
FROM Rbh
I know that, in at least some of the SQL standards, the value expression (the argument to the AVG() function) isn't allowed to be a datetime value or a string value. I haven't read all the SQL standards, but I'd be surprised if that restriction had loosened over the years.
In part, that's because "average" (or arithmetic mean) of 'n' values is defined to be the sum of the values divided by the 'n'. And the expression '01-Jan-2012 08:00' + '03-Mar-2012 07:53' doesn't make any sense. Neither does '01-Jan-2012 08:00' / 3.
Microsoft products have a history of playing fast and loose with SQL by exposing the internal representation of their date and time data types. Dennis Ritchie would have called this "an unwarranted chumminess with the implementation."
In earlier versions of Microsoft Access (and maybe in current versions, too), you could multiply the date '01-Jan-2012' by the date '03-Mar-2012' and get an actual return value, presumably in units of square dates.
If your dbms supports the "interval" data type, then taking the average is straightforward, and does what you'd expect. (SQL Server doesn't support interval data types.)
create table test (
n interval hour to minute
);
insert into test values
('1:00'),
('1:30'),
('2:00');
select avg(n)
from test;
avg (interval)
--
01:30:00

What instead of CONVERT(TIME, x) Datepart?

I have complicated query over very big table.
Long story short, when I use convert time to select period of day (let's say 12-13h, converting it from datetime row) query takes few minutes, instead of few seconds without convert!
So, I tried datepart, and it works well, almost instant, but, problem is, how to point to hours and minutes in same time?
Any other fast solution is more than welcome.
Thanks.
Meanwhile I came up with this:
DATEPART(HOUR, datetimecolumn)*100 + DATEPART(MINUTE, datetimecolumn)) between 1210 and 1540
You can use datePart if you are willing to do a bit of math, as shown below:
12:10 = 12 * 60 + 10 = 730 minutes
15:40 = 15 * 60 + 40 = 940 minutes
select * .....
where datepart(mi, datefield) between (12*60+10) and (15*60+40)
If you have a constant periods - i.e. - always hourly and no any floating periods - you may introduce something like "ordinal number of period" calculated field, index on it and query of it with precalculated period value
OR
is there are no any constant periods - try to calculate proper begin and end values prior to SELECT statement and use them in the query.
Keep in mind that using functions in where clause of query - sometimes is a bad idea. Using functions in ORDER BY clause - always bad
You can get GETTIME from following Function
alter function GetTimeOnly(#_DateTime DateTime)
returns datetime
as
begin
return dateadd(day, -datediff(day, 0, #_datetime), #_datetime)
end
go
OR YOU CAN HAVE THE TIME FROM CONVERT FUNCTION.
SELECT
CONVERT(VARCHAR(8),GETDATE(),108) AS HourMinuteSecond,
CONVERT(VARCHAR(8),GETDATE(),101) AS DateOnly

Time Over 23:59:59 in PostgreSQL?

In MySQL I can create a table with a time field, and the value can be as high as 838:59:59 (839 hours - 1 second). I just read that in PostgreSQL, the hour field cannot exceed 23:00:00 (24 hours). Is there a way around this? I'm trying to make a simple DB that keeps track of how many hours & minutes were spent doing something, so it'll need to go higher than 23 hours & some minutes. I can do this in MySQL, but I need to use PostgreSQL for this. I Googled, but didn't find what I'm looking for, so I'm hoping I just didn't use the right keywords.
Postgres has no "hour field" - it has a few date/time types which serve different needs. The type I believe best fits your needs is INTERVAL.
Although they use the same notation, there's a difference between time of day and elapsed time. Some of their values overlap, but they're different domains. 838 isn't a valid value for an hour if you're talking about a time of day. 838 is a valid value for an hour if you're talking about elapsed time.
This distinction leads to two different data types: timestamp and interval.
create table intervals (
ts timestamp primary key,
ti interval not null
);
insert into intervals values (current_timestamp, '145:23:12');
select *
from intervals;
2011-08-03 21:51:16.837 145:23:12
select extract(hour from ti)
from intervals
145
I believe you are right, but It should not be an issue to work around. Would suggest storing the UNIX time integers for when you "punch in" and out again, and then adding the delta to an int field.
This will yield the number of seconds spent, which can be translated trivially into an hours:minutes:seconds format.
The delta (difference) can be calculated by subtracting the start timestamp from the end timestamp.
you could use a datetime field... 839 hours being something on the order 34.9 days...