Could any one help me to make my query more efficient? I'm a beginner of SQL, as I know for efficient is to use index or primary key to let the B-tree search faster,therefore,I've already set the primary key for rid
and index for (Date, Time)
However, my query is still too inefficient to output the result.
I'm trying to find the sensor(sid) which has the largest interval on '2017-03-04'. Here is my code:
select tmp4.sid as largest_ivl_sensor
from
(
select tmp3.sid, MAX(tmp3.Dif) as max_for_each
from
(
select tmp1.sid, MIN(TIME_TO_SEC(DATE_SUB(tmp2.Time, INTERVAL tmp1.Time HOUR_SECOND))) as Dif
from
(
select se.sid, r.rid, r.Time
from (select rr.rid, rr.Time from records rr where rr.Date = '2017-03-04') as r, send se
where se.rid = r.rid
order by se.sid
) as tmp1
INNER JOIN
(
select se2.sid, r2.rid, r2.Time
from (select rr2.rid, rr2.Time from records rr2 where rr2.Date = '2017-03-04') as r2, send se2
where se2.rid = r2.rid
order by se2.sid
) as tmp2 ON tmp1.sid = tmp2.sid and TIME_TO_SEC(tmp1.Time) <= TIME_TO_SEC(tmp2.Time) and tmp1.rid <> tmp2.rid
GROUP BY tmp1.sid, tmp1.Time
) as tmp3
GROUP BY tmp3.sid
) as tmp4
group by tmp4.max_for_each
having tmp4.max_for_each = MAX(tmp4.max_for_each);
And here is the schema: records
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| rid | int(11) | NO | PRI | NULL | |
| Date | date | YES | MUL | NULL | |
| Time | time | YES | | NULL | |
| Humidity | double(5,2) | YES | | NULL | |
| Temperature | double(5,2) | YES | | NULL | |
| PM1 | int(11) | YES | | NULL | |
| PM10 | int(11) | YES | | NULL | |
| PM25 | int(11) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
send
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| sid | varchar(30) | NO | | NULL | |
| rid | int(11) | NO | PRI | NULL | |
+-------+-------------+------+-----+---------+-------+
Here is a example:
| rid |sid | Time |
| 1 | a | 00:00:00 |
| 2 | a | 00:01:00 |
| 3 | b | 00:05:00 |
| 4 | b | 00:07:00 |
| 5 | b | 00:11:00 |
| 6 | c | 00:00:00 |
| 7 | c | 00:03:00 |
| 8 | c | 00:04:00 |
desired result:
| sid|
| b|
Since it has largest interval 4 minutes
Another example:
| rid |sid | Time |
| 1 | a | 00:00:00 |
| 2 | b | 00:11:00 |
| 3 | c | 00:04:00 |
| 4 | b | 00:07:00 |
| 5 | a | 00:01:00 |
| 6 | c | 00:00:00 |
| 7 | c | 00:03:00 |
| 8 | b | 00:05:00 |
Thanks for helping me.
You could make use of variables in your SQL to keep track of the differences on-the-fly. Also, order by
in combination with limit 1
is handy for getting the record with the highest value:
select sid,
max(diff) as max_diff
from (
select if(sid = @s, secs - @t, null) as diff,
@t := secs as secs,
@s := sid as sid
from (select sid,
time_to_sec(time) as secs
from records
inner join send on send.rid = records.rid
where date = '2017-03-04'
order by sid, time
) ordered
cross join (select @s := null, @t := null) init
) data
group by sid
order by max_diff desc
limit 1;
See it run on rextester.com .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.