如何在Oracle中完成此LAG计算

时间:2014-03-24 13:52:55

标签: sql oracle

我在表格中有月份和值列,例如

Month              Value        Market
2010/01            100            1  
2010/02            200            1
2010/03            300            1
2010/04            400            1
2010/05            500            1
2010/01            100            2  
2010/02            200            2
2010/03            300            2
2010/04            400            2
2010/05            500            2

我想要做的是使用(月份(n-1)中的值+月份(n)中的值)/ 2 =月份n中的值来获取新的月份和值组合,此计算也基于市场列,按市场编号分组。因此,对于上面的示例,新月份和值组合应为

Month                Value         Market
2010/01            null               1
2010/02            (100+200)/2        1
2010/03            (200+300)/2        1
2010/04            (300+400)/2        1
2010/05            (400+500)/2        1
2010/01            null               2
2010/02            (100+200)/2        2
2010/03            (200+300)/2        2
2010/04            (300+400)/2        2
2010/05            (400+500)/2        2

您知道如何在Oracle中实现它吗?谢谢!

2 个答案:

答案 0 :(得分:5)

如果您的数据没有差距,可以使用LAG

SQL> WITH DATA AS (
  2     SELECT DATE '2010-01-01' mon, 100 val FROM dual UNION ALL
  3     SELECT DATE '2010-02-01' mon, 200 val FROM dual UNION ALL
  4     SELECT DATE '2010-03-01' mon, 300 val FROM dual UNION ALL
  5     SELECT DATE '2010-04-01' mon, 400 val FROM dual UNION ALL
  6     SELECT DATE '2010-05-01' mon, 500 val FROM dual
  7  )
  8  SELECT mon, (LAG(val) OVER (ORDER BY mon) + val) / 2 avg_val FROM DATA;

MON            AVG_VAL
----------- ----------
01/01/2010  
01/02/2010         150
01/03/2010         250
01/04/2010         350
01/05/2010         450

但是,如果存在差距,结果可能与您的预期不符。在这种情况下,您可以使用自联接或缩小窗口子句:

SQL> WITH DATA AS (
  2     SELECT DATE '2010-01-01' mon, 100 val FROM dual UNION ALL
  3     SELECT DATE '2010-02-01' mon, 200 val FROM dual UNION ALL
  4     SELECT DATE '2010-03-01' mon, 300 val FROM dual UNION ALL
  5     /* gap ! */
  6     SELECT DATE '2010-05-01' mon, 400 val FROM dual UNION ALL
  7     SELECT DATE '2010-06-01' mon, 500 val FROM dual
  8  )
  9  SELECT mon, (first_value(val)
 10                 OVER (ORDER BY mon
 11                       RANGE BETWEEN INTERVAL '1' MONTH PRECEDING
 12                                 AND INTERVAL '1' MONTH PRECEDING)
 13               + val) / 2 avg_val
 14    FROM DATA;

MON            AVG_VAL
----------- ----------
01/01/2010  
01/02/2010         150
01/03/2010         250
01/05/2010  
01/06/2010         450

答案 1 :(得分:3)

这样做:

SQL> select month,
  2         (value+lag(value) over (order by month))/2 as value
  3* from t1

MONTH           VALUE
---------- ----------
2010/01
2010/02           150
2010/03           250
2010/04           350
2010/05           450

5 rows selected.