select several averages of an interval - mysql

So my coworker is looking at a schema which could be described as something like this:
+--------------------+-----------+
| DATETIME timestamp | INT value |
+--------------------+-----------+
Every 5 minutes a row is entered with the value for that moment.
Here's where it gets tricky. He wants to get the average of every 8 hour period within a 7 day interval.
Certainly, I can think of solutions which involve some client side code, we were wondering if it was possible to do more in SQL.
So in essence, he wants:
SELECT timestamp, value
FROM table
WHERE timestamp >= NOW() - INTERVAL 7 DAYS
AND timestamp <= NOW();
And then breaking that up into 8 hour blocks, and averaging the contents of each block. (each block should have 12 rows, and there should be 3 blocks per day).

try
SELECT avg(`value`)
FROM `table`
WHERE timestamp >= NOW() - INTERVAL 7 DAY AND timestamp <= NOW()
group by concat(date(`timestamp`), case when hour(`timestamp`) between 0 and 7 then 1
when hour(`timestamp`) between 8 and 15 then 2
else 3 end)

If you are not tied by only doing it in your request, you could try the following method of splitting the intervals before doing the request :
boundary1 = NOW()
boundary2 = NOW()
FOR i = 0 to 21 //7 days, 3 intervals of 8 hours per days
boundary1 = boundary2
boundary2 = boundary1 - seconds(8 hours)
req = "SELECT timestamp, value FROM table WHERE timestamp >= "+boundary2+" AND timestamp <= "+boundary1
ENDFOR

Related

How to get records that are less than n minutes?

I am trying to get the records from php that every row have following table:
[created_at] => 2022-10-15 08:17:52
I want get record that are created last minute.
for that i my php file:
SELECT * FROM customer_billing_details WHERE DATE_ADD(created_at, INTERVAL 1 MINUTE) >= NOW();
but it returning the same row even after it is more than 1 minute old,
I dont able to understand what is happening.
You do not need >= NOW(). the interval will automatically handle the time interval. use something like
SELECT *
FROM `customer_billing_details`
WHERE `created_at` >= CURRENT_TIMESTAMP - INTERVAL 5 MINUTE;
Change 5 minutes to 1 or 2 according to your needs.

Dynamic due date finder in a single query

id start_date interval period
1 2018-01-22 2 month
2 2018-02-25 3 week
3 2017-11-24 3 day
4 2017-07-22 1 year
5 2018-02-25 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). requirement is, Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
I am using mysql 5.7. I found a way to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions but its a performance killer and we can't do populate virtual records every time a client request comes.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query.
SELECT b.*
FROM (SELECT a.*,
CASE
WHEN period = 'week' THEN MOD(Datediff('2018-07-22', start_date), 7 * intervals)
WHEN period = 'month'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(YEAR_MONTH FROM start_date)), intervals) = 0 THEN 0
WHEN period = 'year'
AND Day('2018-07-22') = Day(start_date)
AND MOD(Period_diff(201807, Extract(
YEAR_MONTH FROM start_date)) / 12,
intervals) = 0 THEN 0
WHEN period = 'day' THEN MOD(Datediff('2018-07-22', start_date) , intervals)
end filters
FROM kml_subs a)b
WHERE b.filters = 0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
My desired result shoud be like..
if i give two dates.say 2030-05-21 & 2030-05-27. due dates falls under those 6 dates between(2030-05-21 & 2030-05-27) will be shown in the result.
id
1
4
My question is different from Using DATE_ADD with a Column Name as the Interval Value . I am expecting a dynamic way to check due dates based on start_date
Thanks, Kannan
In MySQL, it would seem that a query along these lines would suffice. (Almost) everything else could and should be handled in application level code...
SELECT *
, CASE my_period WHEN 'day' THEN start_date + INTERVAL my_interval DAY
WHEN 'week' THEN start_date + INTERVAL my_interval WEEK
WHEN 'month' THEN start_date + INTERVAL my_interval MONTH
WHEN 'year' THEN start_date + INTERVAL my_interval YEAR
END due_date
FROM my_table;

MSQL, Query rows passed a certain date of an initial date?

How do i extract all rows greater then 7 days of a start date?, I'm trying to use this query in MySQL. Below is my statement.
SELECT * from v_polygons a
INNER JOIN tblProjectData z
on z.Project_ID = a.Project_ID
WHERE DATE_ADD(z.FlyDate, INTERVAL 7 DAY) > NOW() + INTERVAL rge DAY
I have a start date z.FlyDate, So i give it +7 days, then i check to see if that date is greater then NOW()
is this correct or have i messed it up?
You can just do:
WHERE DATE_ADD(DATE(z.FlyDate), INTERVAL 7 DAY) < DATE(NOW());
This will ignore the time part. You can remove DATE function call if you want to consider the time as well.

Check if a timestamp column value is more than six months old

I have a table t_windows_updates which has two columns ci_id and update_installed_on. Table will be having all the windows updates happened to all the assets in my environment.
Data will be like
ci_id| update_installed_on
1 | 1452364200000
1 | 1453055400000
2 | 1441650600000
2 | 1441650600000
2 | 1441650600000
I want to get all ci_ids for which the latest update didn't happen in the last six months.
My Query is
SELECT t.ci_id FROM `t_windows_update` t
GROUP BY t.ci_id
HAVING MAX(t.update_installed_on)<= (NOW() - INTERVAL 6 MONTH);
It is running but getting wrong results.
Your problem is the date format.
I think this is a unix format in milliseconds. So, this suggests something like:
having max(t.update_installed_on) <= UNIT_TIMESTAMP(CURDATE() - INTERVAL 6 MONTH) * 1000
I realize that the above could have overflow issues with integers, so let's go the other way:
having max(t.update_installed_on) / 1000 <= UNIT_TIMESTAMP(CURDATE() - INTERVAL 6 MONTH)

PHP Select from MySQL where date field is 7 days in the future

I have an automatic checker that checks for domains that are going to expire within the next 7 days and it sends and email to the customer.
Im using this SQL Query:
SELECT * from domain_names where status = '' or status = 'valid' and expiry_date = DATE(NOW() + INTERVAL 7 DAY)
but its not working correctly. i need it to check for rows with an expiry_date that is 7 days in the future exactly. also if the checker stops running and it misses some rows for the amount of time its not running it needs to do those rows too
You've probably defined expiry_date as a datetime value, which means your comparisons are incorrect. e.g. you need to use
SELECT ... WHERE date(expiry_date) = date(now() + interval 7 day)
instead (note the wrapping of the +7 day in a date() operation.
e.g.
Given a table with a date and a datetime field:
+------------+---------------------+
| d | dt |
+------------+---------------------+
| 2013-06-28 | 2013-06-28 08:23:03 |
+------------+---------------------+
Notice how the comparison comes out:
mysql> select d=now(), d=date(now()), dt=now(), dt=date(now()), now() from x;
+---------+---------------+----------+----------------+---------------------+
| d=now() | d=date(now()) | dt=now() | dt=date(now()) | now() |
+---------+---------------+----------+----------------+---------------------+
| 0 | 1 | 0 | 0 | 2013-06-28 08:26:20 |
+---------+---------------+----------+----------------+---------------------+
1 row in set (0.00 sec)
date v.s. datetime = false
date v.s date = true
datetime v.s. datetime = false (hh:mm:ss doesn't match, so not equal)
datetime v.s. date = false (date is expanded out to yyyy-mm-hh 00:00:00 and the hh:mm:ss don't match
You have to use parentheses with your and/or conditions
SELECT * from domain_names
where (status = '' or status = 'valid')
and expiry_date = curdate() + INTERVAL 7 DAY
or use in in your case
SELECT * from domain_names
where status in ('', 'valid')
and expiry_date = curdate() + INTERVAL 7 DAY
Assuming your expiry date is a correct datetime field
expiry_date=DATE_ADD(NOW(), INTERVAL 7 DAY)
more reliable than
expiry_date=DATE(NOW() + INTERVAL 7 DAY)
Actually thinking about it if you want exactly 7 days in the future you'd have to use a datediff too
Something like this to return only requests where the expiry date is exactly 7 days from today.
DATEDIFF(expiry_date,DATE(NOW() + INTERVAL 7 DAY))=7
Though this isn't fool proof you're better off letting it check against all days between now and 7 days in the future and then if it is setting an "email sent" flag in your database so then you can confirm the email was actually sent rather than blindly trusting a script to have worked.
If you need to advise the rows missed during the checker stops running, meaby you should use a extra tag to indicate if the domain have been advise or not.
After that, you must select all the rows with date lower than now + 7 days and tag as "not advised".
After sending the email tag it as "advised". And when they re-new the domain tag back as "not advise".
This should give the result as you need:
DATE_SUB(CURDATE(),INTERVAL 7 DAY) = expiry_date;
You can refer to the link below for more details:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
$date=date('Y-m-d');
$date=date('Y-m-d', strtotime($date . ' + 7 day'));
//Now, use this query.
SELECT * from domain_names where status = '' or status = 'valid' and expiry_date = '{$date}';