ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 关于分析函数的一些思考

关于分析函数的一些思考

原创 Linux操作系统 作者:ycpriscilla 时间:2011-10-12 09:48:24 0 删除 编辑

之前在论坛发过一个帖子:
http://www.itpub.net/thread-1495275-1-1.html

二楼给出了一个答案:


代码如下:

SQL> select * from t;

S1       S2       SFHM
-------- -------- ----
20011109 20020311 111
20030214          111
         20110415 111
20011109 20020311 112
20030214          112
         20110415 112
20011109 20020311 444
20030214          444
20111111          444

9 rows selected

SQL>
SQL> select max(s1) keep(dense_rank last order by nvl(s1, s2)) s1,
  2         max(s2) keep(dense_rank last order by nvl(s1, s2)) s2,
  3         sfhm
  4    from t
  5   group by sfhm;

S1       S2       SFHM
-------- -------- ----
         20110415 111
         20110415 112
20111111          444

SQL> 
       
其实是有些问题的。
首先是不满足条件的:当S1全不为空时,则相当于
  1  select max(s1) keep(dense_rank last order by s1) s1,
  2         max(s2) keep(dense_rank last order by s1) s2,
  3         sfhm
  4    from t
  5   group by sfhm;

这样只是按S1排序,完全忽略了S2,而题目要求取同一个身份号码中的所有的S1及所有的S2中最大值所在的记录,相当于所有S1\S2形成的一个集合中的最大的值。同理S1为空而S2不为空时,则相当于只考虑了S2,没考虑S1.
如果
 

S1 S2 SFHM
20021225 20080101 2341
19000101 20110608 2341

则会取到
20021225 20080101 2341
这一条,而实际上是应该取下面一条。


其次:如果改成
max(s1) keep(dense_rank last order by NVL(S1,S2)) s1
max(s2) keep(dense_rank last order by NVL(S2,S1)) s2
当S1、S2全有值是,相当于
     select max(s1) keep(dense_rank last order by s1) s1,
  2         max(s2) keep(dense_rank last order by s2) s2,
  3         sfhm
  4    from t
  5   group by sfhm;

此时: max(s1) keep(dense_rank last order by s1) s1
 
2   max(s2) keep(dense_rank last order by s2) s2
会分别取得所有的S1,S2中的最大值,然而两个最大值未必是从同条记录中取得的,结果如下:20021225   20110608   2341,不是同一条记录中取的。
看通过两次取值来求答案是不行的。

 

10楼给出的答案:
用row_number就可以了,row_number() over(partition by 身份证 order by greatest(s1,s2) desc)
然后去rn=1就可以了

select row_number()over(partition by sfhm order by greatest(s1,s2) desc) RK sfhm from t。
greatest(s1,s2)对SFHM分组,然后在组内对每一条记录选择S1,S2中最大的值生成从小到大的序号,如果一个SFHM有三条记录那么将生成三个1 SFHM\2 SFHM\3 SFHM(1,2,3 是ROW_NUMBER()函数对GREATEST(S1,S2)进行的排名)这种记录,其中1 SFHM是所有S1,S2最大值所条记录中的值。对于本问题,只要取 RK=1的那一条即可。
但是GREATEST()将NULL值排在第一,即GREATEST(1,2,NULL)返回NULL值,故还要修改
select row_number()over(partition by sfhm order by greatest(NVL(s1,'19000101'),NVL(s2,'19000101')) desc) RK sfhm from t 即可。
现在还要在按照ID来排序,这样改:
select row_number()over(partition by sfhm order by greatest(NVL(s1,'19000101'),NVL(s2,'19000101')) desc,ID DESC) RK sfhm from t


只有通过思考,才能将真正的掌握知识。分析函数确实比较复杂,但十分有用,一定要好好学习。




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/24478467/viewspace-709014/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2011-08-18

  • 博文量
    36
  • 访问量
    113903