MySQL-获取上一行数据时查询缓慢

时间:2018-07-04 05:52:42

标签: mysql

我有此查询需要0.04秒的加载时间

SELECT sg.Name AS 'Customer Name', 
m.meter_id AS 'Serial No', 
DATE_FORMAT(datetime, '%Y/%m/%d') AS Date,  
MAX(wh_total) AS Present
FROM meter_data m 
INNER JOIN enrollment e 
ON e.Meter_Id = m.meter_id AND e.Status = 1 
INNER JOIN company_subgroup sg 
ON sg.Id = e.Subgroup_Id 
INNER JOIN company_group g 
ON g.Id = sg.Group_Id 
WHERE date(dateTime) BETWEEN '2018/06/01' AND '2018/06/30' 
AND m.meter_id = '12345' 
AND m.wh_total < 1000000000 
GROUP BY date(datetime)

但是,如果我添加了此“上一个”选择列,则执行该操作大约需要20秒。

SELECT sg.Name AS 'Customer Name', 
m.meter_id AS 'Serial No', 
DATE_FORMAT(datetime, '%Y/%m/%d') AS Date, 
// THIS (main issue)
COALESCE((SELECT MAX(wh_total) FROM meter_data WHERE date(dateTime) < date(m.dateTime) AND meter_id = '12345' 
AND wh_total < 1000000000 GROUP BY date(dateTime) ORDER BY date(dateTime) DESC LIMIT 1),0) AS Previous,
//
MAX(wh_total) AS Present,
// THIS (But I guess this does not affect the query that much since it only substract the two columns) 
ROUND(MAX(wh_total) - MIN((SELECT Previous)),2) AS Consumption 
//
FROM meter_data m 
INNER JOIN enrollment e 
ON e.Meter_Id = m.meter_id AND e.Status = 1 
INNER JOIN company_subgroup sg 
ON sg.Id = e.Subgroup_Id 
INNER JOIN company_group g 
ON g.Id = sg.Group_Id 
WHERE date(dateTime) BETWEEN '2018/06/01' AND '2018/06/30' 
AND m.meter_id = '12345' 
AND m.wh_total < 1000000000 
GROUP BY date(datetime)

基本上,Previous列获取上一行的数据。查询看起来像这样:

Customer Name | Serial No | Date       | Previous | Present | Consumption
ABC           | 12345     | 06/01/2018 | 0        | 1       | 1
ABC           | 12345     | 06/02/2018 | 1        | 3       | 2
ABC           | 12345     | 06/03/2018 | 3        | 8       | 5 
ABC           | 12345     | 06/04/2018 | 8        | 10      | 2 

不幸的是,我尝试使用LAG(column)来获取上一行数据,不幸的是MySQL版本是5.6。有什么方法可以优化此查询?

2 个答案:

答案 0 :(得分:0)

尝试一下

SELECT sg.Name AS 'Customer Name', 
        m.meter_id AS 'Serial No', 
        DATE_FORMAT(datetime, '%Y/%m/%d') AS Date, 
        COALESCE(mx.max_total,0) AS Previous,
        MAX(wh_total) AS Present,
        ROUND(MAX(wh_total) - MIN((mx.max_total)),2) AS Consumption 
FROM meter_data m 
        INNER JOIN enrollment e ON e.Meter_Id = m.meter_id AND e.Status = 1 
        INNER JOIN company_subgroup sg ON sg.Id = e.Subgroup_Id 
        INNER JOIN company_group g ON g.Id = sg.Group_Id 
        LEFT JOIN (SELECT date(dateTime) as dt,  MAX(wh_total) max_total
                    FROM meter_data 
                    WHERE meter_id = '12345' AND wh_total < 1000000000 
                    GROUP BY date(dateTime)) mx on mx.dt < date(m.dateTime)
WHERE date(m.dateTime) BETWEEN '2018/06/01' AND '2018/06/30' 
AND m.meter_id = '12345' 
AND m.wh_total < 1000000000 
GROUP BY date(m.datetime)

注意:如果该内联返回多于一行,则通过添加更多条件来限制该行

答案 1 :(得分:0)

尝试此查询。它将先前的数据存储在用户变量中。

我再次更改了它。 MAX函数出现错误。所以我把它 在子查询中。

SELECT r.`Customer NAME`, r.`SERIAL NO`, r.`DATE` , @prev AS Previous , @reav := r.`Present`
FROM (
    SELECT sg.Name AS `Customer NAME`, 
    m.meter_id AS `SERIAL NO`, 
    DATE_FORMAT(DATETIME, '%Y/%m/%d') AS `DATE`,  
    MAX(wh_total) AS `Present`
    FROM meter_data m 
    INNER JOIN enrollment e 
    ON e.Meter_Id = m.meter_id AND e.Status = 1 
    INNER JOIN company_subgroup sg 
    ON sg.Id = e.Subgroup_Id 
    INNER JOIN company_group g 
    ON g.Id = sg.Group_Id 
    WHERE DATE(DATETIME) BETWEEN '2018/06/01' AND '2018/06/30' 
    AND m.meter_id = '12345' 
    AND m.wh_total < 1000000000 
    GROUP BY DATE(DATETIME)
) AS r
CROSS JOIN (SELECT @prev:=0) AS INIT;