【问题标题】:Offset on query results查询结果的偏移量
【发布时间】:2017-06-15 19:31:07
【问题描述】:

我正在尝试比较每周结果。更具体地说,我想一周又一周地获得差异。

首先我想展示一下结果应该是什么样子:

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

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

【问题讨论】:

    标签: mysql sql join subquery offset


    【解决方案1】:

    改用变量:

    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(),这使得查询更快,逻辑更简单。

    【讨论】:

    • 谢谢。它工作正常。缓存值真是个好主意。这正是我想要的!在 CROSS JOIN 前面只有一个括号。 :)
    猜你喜欢
    • 1970-01-01
    • 2013-09-12
    • 2012-05-30
    • 1970-01-01
    • 2017-09-22
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多