DB2 SQL:获取许多列的滞后值的最快方法

时间:2018-05-30 08:33:54

标签: sql db2 lag

有许多方法可以在SQL中获取某列的滞后值,例如:

WITH CTE AS (
  SELECT
    rownum = ROW_NUMBER() OVER (ORDER BY columns_to_order_by),
    value
  FROM table
)
SELECT
  curr.value - prev.value
FROM CTE cur
INNER JOIN CTE prev on prev.rownum = cur.rownum - 1

,或:

select variable_of_interest 
               ,lag(variable_of_interest ,1) 
                    over(partition by
                    some_group order by variable_1,...,variable_n) 
                    as lag_variable_of_interest
from DATA

我使用的是第二个版本,但是当“滞后”许多变量时,我的代码运行速度很慢,这样我的代码就会变成:

select        variable_of_interest_1
              ,variable_of_interest_2
              ,variable_of_interest_3
                   ,lag(variable_of_interest_1 ,1) 
                        over(partition by
                        some_group order by variable_1,...,variable_n) 
                        as lag_variable_of_interest_1
                    ,lag(variable_of_interest_2 ,1) 
                        over(partition by
                        some_group order by variable_1,...,variable_n) 
                        as lag_variable_of_interest_2
                   ,lag(variable_of_interest_3 ,1) 
                        over(partition by
                        some_group order by variable_1,...,variable_n) 
                        as lag_variable_of_interest_3
    from DATA

我想知道,这是因为每个滞后函数必须通过自己的分区并对整个数据集进行排序,即使它们使用的是相同的分区和顺序吗?

2 个答案:

答案 0 :(得分:2)

我不是100%确定DB2如何优化这些查询。如果它独立地执行每个延迟,那么肯定有改进优化器的空间。

您可以使用的一种方法是lag()主键上有join

select t.*, tprev.*
from (select t.*, lag(id) over ( . . . ) as prev_id
      from t
     ) t left join
     t tprev
     on t.id = tprev.prev_id ;

根据您的描述,这可能是您做任何事情的最有效方法。

这应该比row_number()更有效,因为连接可以使用索引。

答案 1 :(得分:1)

如果所有OLAP函数使用相同的PARTITION BYORDER BY,则Db2将仅对数据进行一次排序。您可以通过查看解释计划来确认这一点。

create table data(v1 int, v2 int, v3 int, g1 int, g2 int, o1 int, o2 int) organize by row
;
explain plan for
select  g1
,       g2
,       o1
,       o2
,       v1
,       v2
,       v3
,       lag(v1) over(partition by g1, g2 order by o1, o2 ) as lag_v1
,       lag(v2) over(partition by g1, g2 order by o1, o2 ) as lag_v2
,       lag(v3) over(partition by g1, g2 order by o1, o2 ) as lag_v3
from
    data
;

将提供以下计划(使用db2exfmt -1 -d $DATABASE)。您可以看到只有一个SORT运算符

Access Plan:
-----------

    Total Cost:             14.839
    Query Degree:           4



      Rows 
     RETURN
     (   1)
      Cost 
       I/O 
       |
      1000 
     LMTQ  
     (   2)
     14.839 
        2 
       |
      1000 
     TBSCAN
     (   3)
     14.5555 
        2 
       |
      1000 
     SORT  
     (   4)
     14.5554 
        2 
       |
      1000 
     TBSCAN
     (   5)
     14.2588 
        2 
       |
      1000 
 TABLE: PAUL    
      DATA
       Q1

顺便说一句如果你发布一个带有真正SQL查询的问题(以及一些DDL和一些数据卷的想法),我们或许能够提出可以改善获得滞后值的性能的事情。如果没有更好的例子,很难提出详细的建议