我正在尝试使用sum()over(partition by),但在该求和中进行过滤。我的用例总结了每个产品一个月的最后12个月,所以:
ITEM MONTH SALES
Item A 1/1/2011 2
Item A 2/1/2011 5
Item A 3/1/2011 3
Item A 4/1/2011 7
Item A 5/1/2011 12
Item A 6/1/2011 8
Item A 7/1/2011 9
Item A 8/1/2011 15
Item A 9/1/2011 6
Item A 10/1/2011 7
Item A 11/1/2011 12
Item A 12/1/2011 1
Item A 1/1/2012 3
Item A 2/1/2012 4
Item A 3/1/2012 5
Item A 4/1/2012 6
Item A 5/1/2012 4
Item A 6/1/2012 8
Item A 7/1/2012 9
Item A 8/1/2012 12
Item A 9/1/2012 14
Item A 10/1/2012 8
Item A 11/1/2012 12
Item A 12/1/2012 16
然后返回:
ITEM MONTH_BEGIN SALES TTM SALES
Item A 1/1/2012 3 87
Item A 2/1/2012 4 88
Item A 3/1/2012 5 87
Item A 4/1/2012 6 89
1/1/12的TTM销售额是1/1 / 11-12 / 1/11的总和
答案 0 :(得分:6)
我就是这样做的Oracle Analytic Functions:
SELECT
"ITEM",
TO_CHAR("MONTH", 'MM/DD/YYYY') AS "MONTH_BEGIN",
"SALES",
SUM("SALES") OVER (
PARTITION BY
"ITEM"
ORDER BY
"MONTH"
RANGE BETWEEN
INTERVAL '12' MONTH PRECEDING
AND
INTERVAL '1' MONTH PRECEDING
) AS "TTM_SALES"
FROM
"SALES"
ORDER BY
"MONTH";
这将计算一个窗口的求和函数,该窗口在当前行的月份之前12个月开始并在其前一个月结束。
我假设您不需要在where子句中过滤任何内容。如果你这样做,请小心。引用Oracle documentation:
分析函数是查询中执行的最后一组操作 除了最后的
ORDER BY
条款。在分析函数之前,所有联接和所有WHERE
,GROUP BY
和HAVING
子句都已完成 处理。
因此,假设您只想显示 2012年第一季度的结果;如果您尝试通过在where子句中进行过滤来实现此目的,那么它也会影响TTM_SALES
的累积结果(输出null
,3
,7
和{{1 }})。
这里的底线是:如果您需要在分析函数的窗口中过滤掉行,请将分析函数移动到子查询,并根据@peterm answer在外部查询中进行过滤:
12
答案 1 :(得分:1)
如果您对分析SUM()
以外的任何其他内容持开放态度,那么这里有一个简单相关子查询的可能解决方案
SELECT s.item, s.month month_begin, s.sales,
(SELECT SUM(sales) FROM sales
WHERE month BETWEEN DATEADD(month, -12, s.month)
AND DATEADD(month, -1, s.month)) ttm_sales
FROM sales s
WHERE s.month BETWEEN '20120101' AND '20121201'
示例输出:
| ITEM | MONTH_BEGIN | SALES | TTM_SALES | ----------------------------------------------------------------- | Item A | January, 01 2012 00:00:00+0000 | 3 | 87 | | Item A | February, 01 2012 00:00:00+0000 | 4 | 88 | | Item A | March, 01 2012 00:00:00+0000 | 5 | 87 | | Item A | April, 01 2012 00:00:00+0000 | 6 | 89 | ...
这是 SQLFiddle 演示