您的位置:首页 > 数据库 > Oracle

oracle分析函数——keep

2015-10-10 10:59 204 查看
原文见我得博客:点击打开链接

1、概念:
keep是Oracle下的另一个分析函数,他的用法不同于通过over关键字指定的分析函数,可以用于这样一种场合下:取同一个分组下以某个字段排序后,对指定字段取最小或最大的那个值。

从这个前提出发,我们可以看到其实这个目标通过一般的row_number分析函数也可以实现,即指定rn=1。但是,该函数无法实现同时获取最大和最小值。或者说用first_value和last_value,结合row_number实现,但是该种方式需要多次使用分析函数,而且还需要套一层SQL。于是出现了keep。

语法:min | max(column1) keep (dense_rank first | lastorder by column2) over (partion by column3);

最前是聚合函数,可以是min、max、avg、sum。。。

column1为要计算的列;

dense_rank first,dense_rank last为keep 函数的保留属性,表示分组、排序结果集中第一个、最后一个;


解释:返回按照column3分组后,按照column2排序的结果集中第一个或最后一个最小值或最大值column1。

2、分析:
SQL> desc t
Name Null? Type
------------------------------------------------- ----------------------------
X VARCHAR2(10)
Y DATE
Z NUMBER

SQL> selectx,to_char(y,'yyyy-mm') y,z from t
2 order by x,y,z
3 /

X Y Z
---------- -----------------
a 2011-02 111
a 2011-02 222
a 2011-02 888
a 2011-03 333
a 2011-04 555
a 2011-04 666
b 2011-02 111
b 2011-02 222
b 2011-03 333
b 2011-04 555

10 rows selected.

SQL>
下面,我们来使用keep函数来看一些例子。
SQL> select x,
2 min(z) keep(dense_rank first order by trunc(y,'mm')) first_min,
3 min(z) keep(dense_rank last order by trunc(y,'mm')) last_min,
4 max(z) keep(dense_rank first order by trunc(y,'mm')) first_max,
5 max(z) keep(dense_rank last order by trunc(y,'mm')) last_max
6 fromt
7 group by x
8 /

X FIRST_MIN LAST_MIN FIRST_MAX LAST_MAX
-------------------- ---------- ---------- ----------
a 111 555 888 666
b 111 555 222 555

这是显示的效果。
我们来分析一下,SQL里面的groupby 是作用于聚会函数的,可以这么理解一下。还有,这里我们头脑里应该有这么一个概念,排序即分组。

结合结果集与keep函数里orderby 子句,我们来看一下表中的数据,然后把表里的数据进行如下划分,
以X为维度,按值a进行划分:
a 2011-02 111
a 2011-02 222
a 2011-02 888
---------------------------------------这些数据划分为第一组。
因为order by是按日期(截止到月)进行排序的,上面的日期都一样。
a 2011-03 333
----------------------------------------这些数据划分为第二组。
a 2011-04 555
a 2011-04 666
----------------------------------------这些数据划分为第三组。
以X为维度,按值b进行划分:
b 2011-02 111
b 2011-02 222
-----------------------------------------第一组
b 2011-03 333
----------------------------------------第二组
b 2011-04 555
----------------------------------------第三组

好,有了上述的划分,我们就不难理解SQL输出的结果集了。下面我们来分析一下SQL中输入的值。结合SQL,

min(z) keep(dense_rank first order by trunc(y,'mm')) first_min 该子句用来显示,以a为维度,以y为序,显示第一组(因为keep函数里指定是的first子句)中的最小值,所以,它显示为111(结合上述的划分结果来看)。

min(z) keep(dense_rank last order by trunc(y,'mm')) last_min 该子句用来显示,以a为维度,以y为序,显示最后一组(因为keep函数里指定是的last子句)中的最小值,所以,这显示为555。


下面,我们来再分析一下以X为b的结果。
我们来看一下x=b的那一行,last_min与last_max的值一样。这是因为x为b的最后一组,它只有一行数据,对于一行数据而言,它的最大值与最小值肯定是同一个值了,所以last_min与last_max一样。

使用其他聚合函数也非常好理解了,比如我使用sum函数。
SQL> select x,
2 sum(z) keep(dense_rank first order by trunc(y,'mm')) first_sum,
3 sum(z) keep(dense_rank last order by trunc(y,'mm')) last_sum
4 fromt
5 group by x
6 /

X FIRST_SUM LAST_SUM
-------------------- ----------
a 1221 1221
b 333 555

原文见我得博客:点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: