计算过时字段的变化(在一段时间内)

时间:2010-05-26 11:55:17

标签: sql postgresql

我有两个包含以下架构的表:

CREATE TABLE sales_data (
     sales_time date NOT NULL,
     product_id integer NOT NULL,
     sales_amt double NOT NULL
);

CREATE TABLE date_dimension (
  id integer  NOT NULL,
  datestamp   date NOT NULL,
  day_part    integer NOT NULL,
  week_part   integer NOT NULL,
  month_part  integer NOT NULL,
  qtr_part    integer NOT NULL, 
  year_part   integer NOT NULL, 
);

我想写两种类型的查询,允许我计算:

  • 期间变更期间(例如,每周更改一次)
  • 期间变更期间的变化(例如,周变化的周变化)

我更愿意在ANSI SQL中编写它,因为我不希望绑定到任何特定的数据库。

[编辑]

根据一些评论,如果我必须绑定到单个数据库(就SQL方言而言),它必须是PostgreSQL

我想写的查询是表格(当然是伪SQL):

Query Type 1 (Period on Period Change)
=======================================
a). select product_id, ((sd2.sales_amt - sd1.sales_amt)/sd1.sales_amt) as week_on_week_change from sales_data sd1, sales_data sd2, date_dimension dd where {SOME CRITERIA)

b). select product_id, ((sd2.sales_amt - sd1.sales_amt)/sd1.sales_amt) as month_on_month_change from sales_data sd1, sales_data sd2, date_dimension dd where {SOME CRITERIA)


Query Type 2  (Change in Period on Period Change)
=================================================
a). select product_id, ((a2.week_on_week_change - a1.week_on_week_change)/a1.week_on_week_change) as change_on_week_on_week_change from 
(select product_id, ((sd2.sales_amt - sd1.sales_amt)/sd1.sales_amt) as week_on_week_change from sales_data sd1, sales_data sd2, date_dimension dd where {SOME CRITERIA)
as a1), 
(select product_id, ((sd2.sales_amt - sd1.sales_amt)/sd1.sales_amt) as week_on_week_change from sales_data sd1, sales_data sd2, date_dimension dd where {SOME CRITERIA) as a2)
WHERE {SOME OTHER CRITERIA}

1 个答案:

答案 0 :(得分:2)

PostgreSQL 8.4具有窗口函数,可以帮助计算周期变化,而无需将表连接到自身。

例如,要进行逐周比较:

create view week_on_week_sales as
select week_part,
       week_sales,
       lag(week_sales, 1) over(order by week_part) as previous_week_sales
from (select week_part,
             sum(sales_amt) as week_sales
      from sales_data
           join date_dimension 
                on sales_data.sales_time = date_dimension.datestamp
      group by date_dimension.week_part) x
order by week_part

与获得二阶导数类似,您可以将其包含在另一个子查询中:

select week_part,
       week_sales - previous_week_sales as change,
       week_sales - previous_week_sales
              - lag(week_sales - previous_week_sales, 1) over(order by week_part)
              as change_in_change
from week_on_week_sales

我认为,窗口语法在SQL:2003标准化了。但是,实现并不完全相同。例如,SQL Server显然不实现LEAD()和LAG()函数。我在Postgresql 8.4上测试了这个。 Oracle支持类似的功能(Postgresql通常遵循Oracle),我相信DB2也支持这些查询,尽管确切的语法可能有所不同。其他