mysql time comparison - mysql

I have job_start and job_end times and timediff will give me the time difference. Now I want to see if that job took more than 2 hrs 30 min. How do I compare it? I am getting errora if I do it like this:
timediff(job_start,job_end)> '2:30:00'
timediff(job_start,job_end)> time(2:30:00)
timediff(job_start,job_end)> time_format(2:30:00)
Nothing of the above syntax is working.

From mysql docs for function TIMESTAMPDIFF:
The unit for the result (an integer) is given by the unit argument.
The legal values for unit are the same as those listed in the description of the TIMESTAMPADD() function.
Which should be one of the following values: MICROSECOND (microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR.
Result if integer.I recommend MINUTE:
TIMESTAMPDIFF(MINUTE, job_start, job_end) > 150
(2 * 60 + 30) mins = 150 mins = 2,5 hours

Related

Generating time series reports

I'm trying to work out how to create a solution that will allow me to query a table that has a timestamp, and in return get a time series data. The request consists of start/end date & time, granularity type (minute, hour, day, week, month and year) and granularity value. Having tried to use in a query something like
GROUP BY ROUND(UNIX_TIMESTAMP(created_at) DIV 60)
to get the results per one minute, or DIV 300 for every five minutes is fine. The problem lies further up for calculating months and years' seconds which will be inaccurate. I've stumbled upon the generate_series in PGSQL (MySQL alternative) and am stuck trying to tie them together. How do I calculate a count of rows, for example, for two days, on a 15 minute granularity? It's a complex question that I'll probably have to break down further.
I have already visited #1 and #2, but they are incomplete.
To me it seems that rounding will only be allowed to certain level and I'd have to restrict it (i.e .for 2 months period there cannot be hourly breakdown).
EDIT
It gave me the wrong impression - I would not have to calculate monthly figures based on seconds using the query like:
SELECT DATE_FORMAT(MIN(created_at),'%d/%m/%Y %H:%i:%s' as date,
COUNT(*) AS count FROM guests
GROUP BY ROUND(UNIX_TIMESTAMP(created_at) / 300)
It's only going to do grouping based on minimum value. But the question still stands - is the best approach really to go through the time period using granularity value and "slice" the data that way without loosing too much accuracy?
It seems that the only approach is to run sub-queries for a set of data (i.e. for a period of two months, generate 15 minute intervals timestamps, group the data into them and produce an aggregate) without dividing the original timestamp to produce the rounded approximation.
Let's say you have a gigantic table measure with two columns datestamp and temp.
Let's say you want to see the temperature every six minutes (10x per hour) for the last week. You can do this sort of thing. We'll get to defining trunc in a moment.
SELECT trunc(datestamp) datestamp, AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY trunc(datestamp)
ORDER BY trunc(datestamp)
That works for any reasonable definition of trunc. In this case trunc(t) returns the beginning of the six-minute period in which t occurs. So, trunc('1942-12-07 08:45:17') gives 1942-12-07 08:42:00).
Here's a query that works for every six minute interval.
SELECT DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD 6) datestamp,
AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD 6)
ORDER BY 1
This uses inbuilt date arithmetic rather than unix timestamp arithmetic.
You can use a stored function to make this easier to read.
DELIMITER $$
DROP FUNCTION IF EXISTS TRUNC_N_MINUTES$$
CREATE
FUNCTION TRUNC_N_MINUTES(datestamp DATETIME, n INT)
RETURNS DATETIME DETERMINISTIC NO SQL
COMMENT 'truncate to N minute boundary. For example,
TRUNCATE_N_MINUTES(sometime, 15) gives the nearest
preceding quarter hour'
RETURN DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD n) MINUTE$$
DELIMITER ;
Then your query will say
SELECT TRUNC_N_MINUTES(datestamp, 6) datestamp, AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY TRUNC_N_MINUTES(datestamp, 6)
ORDER BY TRUNC_N_MINUTES(datestamp, 6)
If you want to summarize by 5, 10, 15, or minute boundaries (three items per hour) simply use that number in place of 6.
You'll need different trunc() functions for hours, etc.
The trunc() function for daily summaries is DATE(datestamp).
For monthly summaries it is LAST_DAY(datestamp). For example,
SELECT LAST_DAY(datestamp) month_ending, AVG(temp) temp
FROM measure
GROUP BY LAST_DAY(datestamp)
ORDER BY LAST_DAY(datestamp)
yields a month-by-month summary.

Recent records by TIME field in MySQL

I have a simple table that has a TIME column named timeC in the example below. I want to select all the records for which timeC is in the last five minutes. I have tried the following and many variations without success.
SELECT * FROM sample_schema.`exampleTable`
WHERE MINUTE(TIMEDIFF(SELECT TIME(NOW())), `timeC`)<5;
Note that the column is TIME, not DATETIME or TIMESTAMP.
Suggestions?
Your parentheses are in the wrong places. So you're calling TIMEDIFF() with 1 argument, and calling MINUTE() with 2 arguments. Also, you don't need to use SELECT to get TIME(NOW()), you can just use that function call as an argument.
SELECT *
FROM exampleTable
WHERE MINUTE(TIMEDIFF(TIME(NOW()), timeC)) < 5
However, there's still a problem with this. TIMEDIFF() can return a negative time if timeC is later in the day, but MINUTE() always returns the positive value of the minute, so this will match anything from 5 minutes ago to 5 minutes later. It would be better to simply compare the time with a range:
SELECT *
FROM exampleTable
WHERE timeC BETWEEN TIME(DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AND TIME(NOW())
There's one ramaining problem. If you perform this query shortly after midnight, the time of 5 minutes earlier will be a late time from the previous day. For instance, if it's currently 00:02, 5 minutes earlier will be 23:57, and nothing will match the BETWEEN expression. You need to check for that:
SELECT *
FROM exampleTable
WHERE CASE
WHEN TIME(NOW()) >= '00:05'
THEN timeC BETWEEN TIME(DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AND TIME(NOW())
ELSE timeC BETWEEN '00:00' AND TIME(NOW())
OR
timeC BETWEEN TIME(DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AND '23:59:59'
END

mysql timestampdiff always returning null?

I am using version 14.4 of mysql and I am trying to execute the following query:
SELECT TIMESTAMPDIFF(MINUTE, MINUTE(NOW()), NOW())
This should return a timestamp that is on the current hour, but it's always returning null. TIMESTAMPADD works just fine, I am only having trouble with this function. I have looked for answers to this problem through google and mysql documentation but I couldn't find anything.
Does anyone have any an idea on what's going wrong?
My full goal is a query that returns how many minutes are left from now until 5 of the next hour. For example. If its 1:30, our target time is 1:55, so the query would return 25
If you want the hour
SELECT CURTIME()
That query you posted is absurd,or be more clear about what you want.
I believe you're trying to floor the current UNIX timestamp to the current hour? If so, why not be explicit about it?
SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP() % 3600;
Based on your edits, you can also calculate the difference to the 5 minute mark preceding the next hour as follows:
SELECT MINUTE( TIMEDIFF(
NOW(),
FROM_UNIXTIME( UNIX_TIMESTAMP() - UNIX_TIMESTAMP() % 3600 + 3600 - 5*60 )
) );
This is just a proof-of-concept query; I haven't yet accounted for rounding the current time to the minute (because I don't know if you want to go up or down), nor handled the edge case where the current time is within 5 minutes of the next hour already (e.g. 1:59).

MYSQL Date Time Round To Nearest Hour

I have a date time field in a MySQL database and wish to output the result to the nearest hour.
e.g. 2012-04-01 00:00:01 should read 2012-04-01 00:00:00
Update: I think https://stackoverflow.com/a/21330407/480943 is a better answer.
You can do it with some date arithmetic:
SELECT some_columns,
DATE_ADD(
DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00"),
INTERVAL IF(MINUTE(the_date) < 30, 0, 1) HOUR
) AS the_rounded_date
FROM your_table
Explanations:
DATE_FORMAT: DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") returns the date truncated down to the nearest hour (sets the minute and second parts to zero).
MINUTE: MINUTE(the_date) gets the minute value of the date.
IF: This is a conditional; if the value in parameter 1 is true, then it returns parameter 2, otherwise it returns parameter 3. So IF(MINUTE(the_date) < 30, 0, 1) means "If the minute value is less than 30, return 0, otherwise return 1". This is what we're going to use to round -- it's the number of hours to add back on.
DATE_ADD: This adds the number of hours for the round into the result.
Half of the hour is a 30 minutes. Simply add 30 minutes to timestamp and truncate minutes and seconds.
SELECT DATE_FORMAT(DATE_ADD(timestamp_column, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') FROM table
soul's first solution truncates instead of rounding and the second solution doesn't work with Daylight Savings cases such as:
select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));
Here is an alternate method (1):
DATE_ADD(
tick,
INTERVAL (IF((MINUTE(tick)*60)+SECOND(tick) < 1800, 0, 3600) - (MINUTE(tick)*60)+SECOND(tick)) SECOND
)
If you don't need to worry about seconds you can simplify it like this (2):
DATE_ADD(
tick,
INTERVAL (IF(MINUTE(tick) < 30, 0, 60) - MINUTE(tick)) MINUTE
)
Or if you prefer to truncate instead of round, here is simpler version of soul's method (3):
DATE_SUB(tick, INTERVAL MINUTE(tick)*60+SECOND(tick) SECOND)
EDIT: I profiled some of these queries on my local machine and found that for 100,000 rows the average times were as follows:
soul's UNIXTIME method: 0.0423 ms (fast, but doesn't work with DST)
My method 3: 0.1255 ms
My method 2: 0.1289 ms
Ben Lee's DATE_FORMAT method: 0.1495 ms
My method 1: 0.1506 ms
From How to round a DateTime in MySQL?:
It's a little nasty when you do it with datetime data types; a nice candidate for a stored function.
DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE ),
INTERVAL SECOND(time) SECOND)
It's easier when you use UNIXTIME timestamps but that's limited to a 1970 - 2038 date range.
FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300))
Good luck.
To round down to the current hour, select:
FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(column_name) / 3600) * 3600).
The value is expressed in the current time zone doc
This will return the next hour, that is '2012-01-02 18:02:30' will be converted into '2012-01-02 19:00:00'
TIMESTAMPADD(HOUR,
TIMESTAMPDIFF(HOUR,CURDATE(),timestamp_column_name),
CURDATE())
Instead of CURDATE() you can use an arbitrary date, for example '2000-01-01'
Not sure if there could be problems using CURDATE() if the system date changes between the two calls to the function, don't know if Mysql would call both at the same time.
to get the nearest hour would be:
TIMESTAMPADD(MINUTE,
ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60,
CURDATE())
changing 60 by 15 would get the nearest 15 minutes interval, using SECOND you can get the nearest desired second interval, etc.
To get the previous hour use TRUNCATE() or FLOOR() instead of ROUND().
Hope this helps.
If you need to round just time to next hour you may use this:
SELECT TIME_FORMAT(
ADDTIME(
TIMEDIFF('16:15', '10:00'), '00:59:00'
),
'%H:00:00'
)
I think this is the best way, since it also will use the least amount of resources-
date_add(date(date_completed), interval hour(date_completed) hour) as date_hr

How to Subtract Days in MySQL

How can I subtract time in MySQL? For example, today is 16 March; I want to subtract 15 days to reach 1 March. Are there any methods that can be used to subtract 15 days from the current date?
SELECT DATE(NOW()-INTERVAL 15 DAY)
For a list of units see http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add
Not entirely related to this question but is related to the title:
SELECT SUBTIME("10:24:21", "5"); -- subtracts 5 seconds. (returns "10:24:16")
SELECT SUBTIME("10:24:21", "01:00:00"); -- subtracts one hour. (returns "09:24:21")
Documentation: MySQL SUBTIME function
Use:
SELECT NOW() - INTERVAL 15 DAY
to keep the datetime precision.
You can use this :
SELECT DATE(NOW()-INTERVAL 15 DAY);
for when you want to subtract the number of days.
In order to subtract the time instead, say 15 minutes, the following should work:
SELECT(DATE_SUB(NOW(), INTERVAL '15:0' MINUTE_SECOND));
Adding the reference link again :- https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add.
Yes its possible using date function in Mysql
select distinct
lastname,
changedat, date_add(changedat, interval -15 day) as newdate
from employee_audit;
lastname and changedat is field name and employee_audit is table name.
I have subtract 15 days from my date - check image please. thanks