I am currently working on a ticket system in which I would like to work out the average amount of time it is taking staff to respond to tickets.
I have 2 columns that hold the UNIX timestamps: timestamp (when ticket was submitted) and endstamp (when ticket was closed)
SELECT AVG(TIMEDIFF(endstamp,timestamp)) AS timetaken FROM `tickets`
I'm not really sure what I am doing wrong.
Any help would be much appreciated!
A UNIX timestamp is just a representation of a point in time as a number of seconds, so basically an integer value. On the other hand, date function timestampdiff() operates on 3 parameters: a unit, and two values (or expressions) of datetime datatype (or the-like). Your query should actually raise a syntax error, since what you are giving as first argument is not a legal unit.
If you want the difference in seconds between two UNIX timestamps, just substract them, so:
SELECT AVG(endstamp - timestamp) AS timetaken FROM `tickets`
Related
I have two String columns in MySQL database. Those two columns were populated from a Java program in following way:
System.currentTimeMillis(); //first column
System.currentTimeMillis(); + someStringHours //second column; the String, someStringDays reprensents some number of days, let's say 5 hours in millis...
Which function in MySQL can be used to calculated the difference to get number of hours between these two columns?
You call them string dates but they are actually UNIX timestamps in milliseconds (also called Javascript timestamps). That's what System.currentTimeMillis() generates. It's a Java long data item, and a MySQL BIGINT data item. You can store it in a string. (You can store it that way if you must, but searching and sorting numbers stored as strings is an unreliable mess; beware!)
A typical Javascript timestamp (or UNIX timestamp in milliseconds) is a big integer like 1600858176374456. 1 600 858 176 374 456.
You can convert such a timestamp to a MySQL TIMESTAMP value with FROM_UNIXTIME() like this
FROM_UNIXTIME(column * 0.001)
Why multiply the column value by 0.001 (that is, divide it by 1000)? Because FROM_UNIXTIME() takes the timestamp in seconds, whereas System.currentTmeMillis() generates it in milliseconds.
Then you can use DATEDIFF() like this
DATEDIFF(FROM_UNIXTIME(laterTs*0.001),FROM_UNIXTIME(earlierTs*0.001))
This gives an integer number of days.
If you need the time difference in some other unit, such as hours, minutes, or calendar quarters, you can use TIMESTAMPDIFF(). This gives you your difference in hours.
TIMESTAMPDIFF(HOUR,
FROM_UNIXTIME(laterTs*0.001),
FROM_UNIXTIME(earlierTs*0.001));
You can use SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR as the time unit in this function.
Pro tip: Use your DBMS's date arithmetic functions if you possibly can. They've worked out all sorts of edge cases for you already.
And, by the way, if you declare your columns like this (Timestamp with a millisecond precision: How to save them in MySQL):
laterTs TIMESTAMP(3),
earlierTs TIMESTAMP(3),
You'll have an easier time indexing on and searching by these times.
SELECT (1600858176374-1600944576374)/(24*60*60*1000) as Days
Where (1600858176374-1600944576374) are timestamps and (246060*1000) is a mills in day
I have created a MySql table and feed data therein with below code
CREATE TABLE IF NOT EXISTS DB (
INN VARCHAR(200) NOT NULL,
Time BIGINT not NULL
);
Now I want to get a table which will report the Maximum and Minimum values of Time when grouped by INN. Below is my code -
SELECT INN, from_unixtime(MIN(Time)), from_unixtime(MAX(Time)) FROM DB GROUP BY INN
I want to get the Time values reported as normal date-time instead of Epoch time. But with above code, I am getting <NA> values.
A typical Time value is like 1546380001264082944
Can someone please help me to get the correct code to achieve the same.
The problem here is to do with the precision of the unix timestamp you are using.
Consider this:
SELECT FROM_UNIXTIME(1546380001), FROM_UNIXTIME(1546380001264082944)
The output is:
2019-01-01T22:00:01Z (null)
The timestampt value you have, 1546380001264082944, contains a level of precision beyond that accepted by MySQL.
The definition of FROM_UNIXTIME is:
FROM_UNIXTIME(unix_timestamp[,format])
The doc states:
unix_timestamp is an internal timestamp value representing seconds
since '1970-01-01 00:00:00' UTC
The precision of your timestamp is significantly greater than seconds since the Unix Epoch.
The docs are available here.
The value 1546380001264082944 is too big to be epoch seconds or even milliseconds. This is easily verified by putting this value on https://currentmillis.com/.
You have stored precision upto a nanosecond. So, divide the column value by 1e9 before passing them to from_unixtime.
SELECT INN, from_unixtime(MIN(Time) / 1000000000), from_unixtime(MAX(Time) / 1000000000)
FROM DB
GROUP BY INN
I'm trying to figure out what MySQL is doing during the math operation of timestamps.
Picture of resulting problem:
You'll see on the left I have two timestamps, start and end, and I need to find the duration from start to end so I just do this:
end - start
I was getting some really weird results. You can see for a duration of only 3 hours I was getting result back that indicated 2 to 3 times that amount.
When I convert to UTC first, the math works out fine.
Can anyone explain what SQL is doing with the timestamps on the left? I've always been under the impression that all timestamps are UTC under the hood, which is why things like min, max, less than, etc work without converting.
Thanks!
Code:
select
min(timestamp) start,
max(timestamp) end,
max(timestamp) - min(timestamp) start_to_end,
unix_timestamp(min(timestamp)) startUTC,
unix_timestamp(max(timestamp)) endUTC,
unix_timestamp(max(timestamp)) - unix_timestamp(min(timestamp)) start_to_end_UTC
from post_snapshots group by permalink;
These examples have nothing to do with timezone conversions -- when you subtract one date directly from the other, MySQL generates a integer from all existing date parts and then makes the math operations. For example, this query:
select now()+1;
returns (it was '2013-02-26 14:38:31' + 1):
+----------------+
| now()+1 |
+----------------+
| 20130226143832 |
+----------------+
So the difference between "2013-02-19 16:49:21" and "2013-02-19 19:07:31" turns out to be:
20130219190731 - 20130219164921 = 25810
The correct way for getting this subtraction is to either convert the dates to timestamps (like you did) or to use TIMESTAMPDIFF(SECOND, start_date, end_date), which would return 8290.
This isn't a DATETIME vs. TIMESTAMP or a time zone problem.
MySQL handles datetimes as operands to a subtraction (or other mathematical operation) by converting each value to a number, but it's not the number of seconds, its just the datetime digits crunched together. Take an example from your data:
2013-02-19 16:49:21 becomes 20130219164921
2013-02-19 19:07:31 becomes 20130219190731
The difference between those two numbers is... 25810, which is the value you're seeing as the result of your subtraction operation. That's not a result in seconds, as you noted. It really doesn't mean much useful at all.
In contrast, TIMESTAMPDIFF() (or pre-converting to Unix timestamps as you did) actually performs the difference using time-appropriate math if you're looking for the difference to be significant for much beyond sorting:
SELECT TIMESTAMPDIFF(SECOND, '2013-02-19 16:49:21', '2013-02-19 19:07:31')
>>> 8290
What happens is you cannot substract dates/datetimes in mysql. For all math operations, the mysql timestamp data type behaves like datetime data type.
You could use instead
select
TIMESTAMPDIFF(SECOND,min(timestamp),max(timestamp))
from post_snapshots group by permalink;
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.
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...