替代lag SQL命令

时间:2010-11-23 23:21:48

标签: sql oracle oracle10g

我有一张桌子,里面有这样的桌子。

Month-----Book_Type-----sold_in_Dollars
Jan----------A------------ 100
Jan----------B------------ 120
Feb----------A------------ 50
Mar----------A------------ 60
Mar----------B------------ 30

等等

我必须根据过去2个月的销售额计算每月的预期销售额和预订类型。 因此对于March和A型,它将是(100 + 50)/ 2 = 75 3月和B型是120/1,因为没有2月的数据。

我试图使用滞后函数,但由于几行中缺少数据,因此无法正常工作。

有关于此的任何想法吗?

4 个答案:

答案 0 :(得分:1)

由于它计划忽略缺失值,这应该可行。目前没有数据库可以测试它,但会在早上再次进行测试

select 
  month, 
  book_type, 
  sold_in_dollars, 
  avg(sold_in_dollars) over (partition by book_type order by month
    range between interval '2' month preceding and interval '1' month preceding) as avg_sales
from myTable;

这种假设月份有一个日期数据类型,并且可以排序...如果它只是一个文本字符串,那么你将需要其他东西。

通常你可以使用rows between 2 preceding and 1 preceding但是这会占用前两个数据点,如果缺少行,则不一定是前两个月。

你可以用延迟来解决这个问题,但这会有点复杂。

答案 1 :(得分:0)

据我所知,你可以给lag()一个默认值:

  SELECT Book_Type, 
         (lag(sold_in_Dollars, 1, 0) OVER(PARTITION BY Book_Type ORDER BY Month) + lag(sold_in_Dollars, 2, 0) OVER(PARTITION BY Book_Type ORDER BY Month))/2 AS expected_sales
    FROM your_table
GROUP BY Book_Type

(假设Month列实际上不包含JAN或FEB,而是真实的,可订购的日期。)

答案 2 :(得分:0)

如何(原谅sql server语法,但你明白了):

Select Book_type, AVG(sold_in_dollars)
from MyTable
where Month in (Month(DATEADD('mm'-1,GETDATE)),Month(DATEADD('mm'-2,GETDATE)))
group by booktype

答案 3 :(得分:0)

分区外连接可以帮助创建缺少的数据。创建一组月份,并按月将这些值连接到每一行,并为每种书籍类型执行一次连接。我在这个例子中创建了1月到4月的月份:

with test_data as
(
  select to_date('01-JAN-2010', 'DD-MON-YYYY') month, 'A' book_type, 100 sold_in_dollars from dual union all
  select to_date('01-JAN-2010', 'DD-MON-YYYY') month, 'B' book_type, 120 sold_in_dollars from dual union all
  select to_date('01-FEB-2010', 'DD-MON-YYYY') month, 'A' book_type, 50 sold_in_dollars from dual union all
  select to_date('01-MAR-2010', 'DD-MON-YYYY') month, 'A' book_type, 60 sold_in_dollars from dual union all
  select to_date('01-MAR-2010', 'DD-MON-YYYY') month, 'B' book_type, 30 sold_in_dollars from dual
)
select book_type, month, sold_in_dollars
  ,case when denominator = 0 then 'N/A' else to_char(numerator / denominator) end expected_sales
from
(
  select test_data.book_type, all_months.month, sold_in_dollars
    ,count(sold_in_dollars) over
      (partition by book_type order by all_months.month rows between 2 preceding and 1 preceding) denominator
    ,sum(sold_in_dollars) over
      (partition by book_type order by all_months.month rows between 2 preceding and 1 preceding) numerator
  from 
    (
      select add_months(to_date('01-JAN-2010', 'DD-MON-YYYY'), level-1) month from dual connect by level <= 4
    ) all_months
    left outer join test_data partition by (test_data.book_type) on all_months.month = test_data.month 
)
order by book_type, month