I have the following query:
SELECT * FROM event_incidents order by last_update desc limit 1;
What I want is to get the first row and check if the last_update time on that row is greater than 10 minutes from the current time.
You can try like this:
select * from event_incidents
where last_update >= (NOW() - INTERVAL 10 MINUTE)
ORDER BY last_update desc
LIMIT 1;
You can do this using aggregation and a comparison in the where. If you have an index on last_update then:
SELECT (case when MAX(last_update) >= date_sub(now(), interval 10 minute)
then 'recent'
else 'ancient'
end)
FROM event_incidents ;
I'm not sure what you want to return, so I made up "recent" and "ancient".
Note:
If you just want a flag on a single row being returned:
SELECT ei.*,
(last_update > date_sub(now(), interval 10 minute)) as RecencyFlag
FROM event_incidents
ORDER BY last_update desc
LIMIT 1;
Related
I have a decent query working now but I need to find the max out of the results. The rssi field.
table layout
id - rssi, item, datetime
My query now is
select
id, rssi
from
table
where
item = 1 and dt > date_sub(now(), interval 1 minute)
I have tried several other answers from around here and they work fine if I do not use the date part but I want to run the query only on the latest entries.
If you want the most recent row:
select id, rssi
from table
where item = 1
order by dt desc
limit 1;
For performance, you want an index on (item, dt desc).
EDIT:
Based on your comment, that would be:
select id, rssi
from table
where item = 1 and dt > date_sub(now(), interval 1 minute)
order by rssi desc
limit 1;
You get the max rssi with max(rssi), as the function name suggests :-)
select max(rssi)
from table
where item = 1 and dt > date_sub(now(), interval 1 minute);
We have a below query which takes approximately 6-8 secs to execute.
Total number of records : 522954
(SELECT
*
FROM
tbl_insights_copy
WHERE insightscat = 21
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
LIMIT 5)
UNION
(SELECT
*
FROM
tbl_insights_copy
WHERE insightscat = 22
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
LIMIT 5)
UNION
(SELECT
*
FROM
tbl_insights_copy
WHERE insightscat = 23
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
LIMIT 5)
UNION
(SELECT
*
FROM
tbl_insights_copy
WHERE insightscat = 24
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
LIMIT 5)
Can someone help to optimize this query as to reduce the execution time.
Thanks in advance.
The only thing you are changing between one select and another, is the filter value of the column insightscat I am not sure that this is what you want but....
You may try the IN instruction for this. Example:
SELECT
*
FROM
tbl_insights_copy
WHERE insightscat in (20,21,22,23,24)
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
For this query:
SELECT ic.*
FROM tbl_insights_copy ic
WHERE insightscat = 21 AND
submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC
LIMIT 5
You want an index on tbl_insights_copy(insightscat, submittedon).
This should work for all the subqueries. This is probably the best approach with MySQL.
SELECT t1.*
FROM (SELECT t.* ,ROW_NUMBER() OVER (ORDER BY insightscat) AS Row
FROM
(select * from
tbl_insights_copy
WHERE insightscat in (20,21,22,23,24)
AND submitedon >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
ORDER BY submitedon DESC ) as t ) t1
WHERE Row <= 5
Without SHOW CREATE TABLE, I am going to have to guess that you do not have the optimal
INDEX(insightscat, submitedon)
Since the SELECTs are distinct, use UNION ALL instead of the default UNION DISTINCT. This will avoid an unnecessary (but fast) de-dup pass over the 20 rows.
If you want 20 rows
If so, my suggestions above might be best.
If you want 6 rows
If you want only the latest 5 from any of those insightscats, then there are 3 possibilities.
Plan A
What Developer90 says in his Comment.
Plan B
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
UNION ALL
( SELECT ... ORDER BY ORDER BY submitedon DESC LIMIT 5)
ORDER BY ORDER BY submitedon DESC LIMIT 5;
Each SELECT is very fast with my index. Then, the 20 rows of the UNION get sorted again and LIMIT 5 is applied. Again, very fast.
Using the IN as suggested by Developer90, may or may not effectively use my index. What version are you using?
Plan C
This option is hit or miss. That is, its performance depends heavily on the distribution of the data as to whether it will be very fast or very slow: Developer90 + INDEX(submitedon) (not including insightscat).
I have the query below to fetch the number of row and group them by week. It works great.
SELECT
WEEKOFYEAR(searched_on) AS weekno,
COUNT(*) AS num_search,
SUBDATE(searched_on, INTERVAL WEEKDAY(searched_on) DAY), INTERVAL + 0 DAY AS date_of_week,
FROM table
GROUP BY WEEK(DATE_SUB(searched_on, INTERVAL 1 DAY)) ORDER BY weekno ASC
How can I modify this in order to select only the last 5 results without using ORDER BY weekno DESC LIMIT 5 in order not to alter the way data has been arranged. Thanks
You could add the ORDER BY weekno DESC LIMIT 5 and push the query into a subquery, then have the outer query reorder ascending:
SELECT * FROM (
SELECT
WEEKOFYEAR(searched_on) AS weekno,
COUNT(*) AS num_search,
SUBDATE(searched_on, INTERVAL WEEKDAY(searched_on) DAY), INTERVAL + 0 DAY AS date_of_week,
FROM table
GROUP BY WEEK(DATE_SUB(searched_on, INTERVAL 1 DAY))
ORDER BY weekno DESC LIMIT 5
) inner
ORDER BY weekno
Simply use the limit used in mysql.
add the limit 5 after the code ORDER BY weekno ASC. means add it at the end of query.
Here is the tutorial.
Example
Use the below query:
SELECT
WEEKOFYEAR(searched_on) AS weekno,
COUNT(*) AS num_search,
SUBDATE(searched_on, INTERVAL WEEKDAY(searched_on) DAY), INTERVAL + 0 DAY AS date_of_week,
FROM table
GROUP BY WEEK(DATE_SUB(searched_on, INTERVAL 1 DAY)) ORDER BY weekno ASC
LIMIT 5 OFFSET (num_search-5) //add this line
I have this SQL:
$sql="SELECT *
FROM table
WHERE expiresdate >= Date(Now())
AND expiresdate <= Date_add(Date(Now()), INTERVAL 10 day)
ORDER BY expiresdate ASC";
it should basically show all rows in the database that are going to expire within 10 days time however, lets say the expiredate was 2013-03-06 - this row will not display on any day after the expiredate
does anyone have any ideas?
This should be what you need:
SELECT
*
FROM
`table`
WHERE
expiresdate <= CURDATE() + INTERVAL 10 DAY
ORDER BY
expiresdate ASC
I always have trouble with complicated SQL queries.
This is what I have
$query = '
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND active = 1
ORDER BY date_time ASC
LIMIT 6
';
I want to get up to 6 rows that are upcoming within the hour. Is my query wrong? It does not seem to get events that are upcoming within the next hour when I test it.
What is the correct syntax for this?
I'm going to postulate that you're looking at a group of records that contain a range of DATETIME values, so you probably want something more like this:
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time < DATE_ADD(NOW(), INTERVAL 1 HOUR)
AND date_time >= NOW()
AND active = 1
ORDER BY date_time ASC
LIMIT 6
Otherwise, your query is looking for records with a date_time of exactly "now + 1 hour". I'm assuming all your dates aren't specific to that particular second. ;)
To clarify a bit, DATE_ADD() and DATE_SUB() return exact timestamps, so your query above roughly translates to something like SELECT ... WHERE date_time = '2010-04-14 23:10:05' ORDER BY ..., which I don't think is what you want.
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
means date_time equals exactly now minus one hour, which would result in any record exactly one hour old.
Why not use
WHERE TIMEDIFF(date_time, NOW()) < '01:00:00'
AND date_time > NOW()