查询结果的偏移量

时间:2017-01-30 15:17:23

标签: mysql sql join subquery offset

我想比较每周结果。更具体地说,我希望每周都能获得不同。

首先,我想说明结果应如何:

CalendarWeek     currently      previous_week      delta
2016-01          200            
2016-02          210            200                 10
2016-03          205            210                 -5
2016-04          230            205                 25
...      

我得到了一个解决方案,但速度很慢。

目前我这样做:

SELECT CalendarWeek, cur_value - prev_value AS delta
FROM  
    (SELECT CalendarWeek, COUNT(Change_ID) AS cur_value
     FROM Changes
     WHERE ...
     GROUP BY CalendarWeek) AS cur_week
LEFT JOIN
    (SELECT CalendarWeek, COUNT(Change_ID) AS prev_value
     FROM Changes
     WHERE ...
     GROUP BY CalendarWeek) AS prev_week
ON cur_week.CalendarWeek = prev_week.CalendarWeek + 1

我的问题是,运行子查询需要花费很多时间(我确实为这个展示简化了它们)。 SELECT COUNT()运行45秒。每个= 1.5分钟。我认为应该有一个更合适的解决方案。我只需要将prev_value移位1行或偏移1行。

1 个答案:

答案 0 :(得分:0)

改为使用变量:

SELECT w.*,
       (CASE WHEN (@pcv := @prev_value) = NULL THEN NULL       -- never happens
             WHEN (@prev_value := cur_value) = NULL THEN NULL  -- never happens
             ELSE @pcv
        END) as prev_value
FROM (SELECT CalendarWeek, COUNT(Change_ID) AS cur_value
      FROM Changes
      WHERE ...
      GROUP BY CalendarWeek AS cur_week
     ) w CROSS JOIN
     (SELECT @prev_value := -1) params
ORDER BY CalendarWeek;

然后,您可以使用其他子查询来计算比率和差异。

注意:分配前一个值的逻辑是一个三步过程:(1)将前一个值缓存到变量中,(2)重新分配先前的值,然后(3)然后使用缓存的值。

MySQL不保证SELECT中表达式的执行顺序,所以这一切都必须在一个表达式中发生(因此= NULL,这永远不会成立)。几乎所有其他数据库都支持lag()用于此目的,这使查询更快,逻辑更简单。