Oracle的分析函数在有些时候很方便,以面向集合的思维重新看待数据。
本次实验数据接 Oracle之Group By
分析函数组成:分区子句、排序子句、开窗子句(滑动窗口)
开窗子句
语法:
[ROWS | RANGE] BETWEEN <Start expr> AND <End expr>
Whereas
<Start expr> is [UNBOUNDED PRECEDING | CURRENT ROW | n PRECEDING | n FOLLOWING]
<End expr> is [UNBOUNDED FOLLOWING | CURRENT ROW | n PRECEDING | n FOLLOWING]
一、以‘年份’、‘月份’、‘类别’、‘销售额’、‘本年最大销售额’格式统计苹果的销售信息
select year, month, category, sales, max(sales) over(partition by year order by year, month rows between unbounded preceding and unbounded following) maxSales from sales_log where category = 'Apple';
结果(省略一部分结果):
YEAR MO CATEGORY SALES MAXSALES ---- -- ---------- ---------- ---------- 2011 1 Apple 709 869 2011 2 Apple 105 869 2011 3 Apple 505 869 2011 4 Apple 869 869 ... 2011 11 Apple 775 869 2011 12 Apple 220 869 2012 1 Apple 226 942 2012 2 Apple 942 942 2012 3 Apple 353 942 ... 2012 10 Apple 785 942 2012 11 Apple 836 942 2012 12 Apple 763 942
解析:
上述查询语句中分区子句:
partition by year
要求“本年最大销售额”首先按照年将数据分成几个区域。
排序子句:
order by year, month按照年份、月份对每个区域中的数据进行排序
开窗子句:
rows between unbounded preceding and unbounded following
窗口为unbounded preceding(前面无边界)unbounded following(后面无边界)
下面画个图解释一下上面三个定义
分区 + 排序 开窗 取得每个窗口的最大值
步骤:
1.按照year进行分区,,共分为三个区域2011、2012、2013
2.按照year,month进行排序
3.无边界开窗(即以整个分区为窗口),求出每个窗口的最大值
这个例子在开窗这块还不明显,下面在举个例子
二、以‘年份’、‘月份’、‘类别’、‘销售额’、‘本月前后一周的最大销售额’格式统计2011年苹果的销售信息
也就是说现在是三月,那么最后一列的值为二月、三月、四月中最大的销售额
SQL> select year, month, category, sales, 2 max(sales) 3 over(order by to_number(month) rows between 1 preceding and 1 following) maxSales 4 from sales_log 5 where category = 'Apple' 6 and year = '2011'; YEAR MO CATEGORY SALES MAXSALES ---- -- ---------- ---------- ---------- 2011 1 Apple 709 709 2011 2 Apple 105 709 2011 3 Apple 505 869 2011 4 Apple 869 869 2011 5 Apple 230 869 2011 6 Apple 460 862 2011 7 Apple 862 862 2011 8 Apple 674 862 2011 9 Apple 257 674 2011 10 Apple 669 775 2011 11 Apple 775 775 2011 12 Apple 220 775 12 rows selected. Elapsed: 00:00:00.00 SQL> spool off
这次就没必要分区了,所有数据只有一个年份2011。但是数据一定要排序,不然月份乱套了。那就没法保证上一条数据就是上月的,写一条数据就是下月的了。
这次的分区子句为
rows between 1 preceding and 1 following也就是前后各一行,符合语法 n PRECEDING | n FOLLOWING
可以把窗口看成一个滑块,如图
---> 2011 1 Apple 709 709 2011 2 Apple 105 2011 3 Apple 505 ... 2011 1 Apple 709 ---> 2011 2 Apple 105 709 2011 3 Apple 505 ... ... 2011 2 Apple 105 ---> 2011 3 Apple 505 869 2011 4 Apple 869 ...
第一次当前行为一月值为709,前一行没有为null,下一行值为105。最大值为709
第二次当前行为二月值为105,前一行一月值为709,下一行三月值为505。最大值为709
第三次当前行为三月值为505,前一行二月值为105,下一行四月值为869。最大值为869
总之开窗子句相当于就是滑动在分区上的一个小滑块,每次滑动一行。滑块的大小(范围)就是开窗子句定义的。而我们每次分析的数据就是滑块中的数据。