MySQL-获取上一行数据会减慢查询速度

时间:2018-07-06 13:43:25

标签: mysql

我有这张桌子

Id | ApplianceId | Energy
1  | 101         | 0.6
2  | 103         | 1.5
3  | 107         | 1.3
4  | 101         | 1.0
5  | 101         | 1.5
6  | 103         | 2.1

我要在查询中显示的是此内容(按ApplianceId过滤),[上一个]是上一个[当前]值,[当前]是能量值,并且[消耗量]存在-上一个:

ApplianceId | Previous | Present | Consumption
101         | 0        | 0.6     | 0.6
101         | 0.6      | 1.0     | 0.4
101         | 1.0      | 1.5     | 0.5

我已经有一个有效的查询,但是它太慢了(原因是获取“上一个”值时)。

SELECT 
    ApplianceId, 
    COALESCE((SELECT MAX(Energy) FROM table WHERE 
    id < t.id AND ApplicationId = '101' ORDER BY id DESC LIMIT 1),0) As Previous,
    Energy AS Present,
    ROUND(MAX(m.wh_total) - (SELECT Previous),2) AS Consumption
FROM
    table t
WHERE ApplicationId = '101'
ORDER BY Id

我正在查询10万条记录,大约需要30秒才能运行。如果删除获取上一行的部分,则只需要0.4秒。有什么我可以优化的方法,或者还有另一种获取上一行值的方法吗?

2 个答案:

答案 0 :(得分:0)

您可以在下面的查询中尝试-

SELECT ApplianceId
      ,COALESCE(LAG(Energy) OVER (ORDER BY ApplianceId),0) PREVIOUS
      ,Energy PRESENT
      ,Energy - COALESCE(LAG(Energy) OVER (ORDER BY ApplianceId),0) FUTURE 
FROM T
WHERE ApplicationId = '101'
GROUP BY ApplianceId, Energy

答案 1 :(得分:0)

由于使用的MySQL没有内置的Analytic函数(自v5.6起),因此必须直接在查询中使用用户定义的变量模拟其行为,然后进行构建分阶段进行。

第一步是模拟按ApplianceID划分并按ID排序的分析LAG函数。这需要三个变量。一个跟踪当前分区,一个跟踪先前的能量,最后一个存储下一个先前的能量(即当前能量)。

select ID
     , case when @pa != ApplianceID
            then @PriorEnergy := 0.0
            else @PriorEnergy := @ce
       end PriorEnergy
     , @pa := ApplianceID ApplianceID
     , @ce := energy Energy
  from table1
 order by ApplianceID, id;

在上面的查询中,case语句处理分区,以便当@pa与当前的ApplianceID不匹配时,将@PriorEnergy变量设置为0.0,否则将@PriorEnergy变量设置为@ce的当前值,该变量保留前一个记录的能量值。在case语句之后,从当前记录更新@pa和@ce以维持状态。上述查询中的排序依据对于确保分区正常工作很重要。

下一步是将上述查询用作较大查询的一部分,以产生最终输出:

select ApplianceID
     , PriorEnergy Previous
     , Energy Present
     , Energy - PriorEnergy Consumption
from (
select ID
     , case when @pa != ApplianceID
            then @PriorEnergy := 0.0
            else @PriorEnergy := @ce
       end PriorEnergy
     , @pa := ApplianceID ApplianceID
     , @ce := Energy Energy
  from table1
  order by ApplianceID, ID) aq1
order by ApplianceID, id;

您可以在此SQL Fiddle中查看以上两个查询的结果。另外,小提琴中有一个third query,显示了如何在第一个分析查询中计算消耗量,但是要满足使分析处理工作所需的列顺序约束,则投影无法满足您的要求要求。