简体   繁体   中英

Could any one help me to make my query more efficient?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM