|
代码如下:
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 | 则会取到
这一条,而实际上是应该取下面一条。
其次:如果改成 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
只有通过思考,才能将真正的掌握知识。分析函数确实比较复杂,但十分有用,一定要好好学习。
|