今天学习sql优化语句过程中,看到有使用keep DENSE_RANK 减少表扫描,以前没有接触过这个,为此我去网上搜了下相关描述,如下所示
DENSE_RANK
功能描述:根据ORDER BY子句中表达式的值,从查询返回的每一行,计算它们与其它行的相对位置。组内的数据按ORDER BY子句排序,然后给每一行赋一个号,从而形成一个序列,该序列从1开始,往后累加。每次ORDER BY表达式的值发生变化时,该序列也随之增加。有同样值的行得到同样的数字序号(认为null时相等的)。密集的序列返回的时没有间隔的数。
FIRST
功能描述:从DENSE_RANK返回的集合中取出排在最前面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。
LAST
功能描述:从DENSE_RANK返回的集合中取出排在最后面的一个值的行(可能多行,因为值可能相等),因此完整的语法需要在开始处加上一个集合函数以从中取出记录。
所以默认排序下,FIRST可以理解是取小值,LAST取大值。而前面的MIN或者MAX则是在KEEP的结果集中取某一字段的最大值或最小值。
下面我们开始动手操作,
create table t(ZGH VARCHAR2(10),WM VARCHAR2(10),RQ VARCHAR2(10)) select * from t for update; --插入以下内容 /*A 1 20130101 A 2 20140102 A 1 20120102 B 3 20131001 B 2 20140102 B 3 20121004 */
易错写法
select t.zgh,min(t.wm),min(t.rq) from t group by t.zgh;
最小值对应的wm为3,错误。
嵌套写法,效率一般
----普通写法 ,嵌套 select t1.zgh,t1.mwm,t2.mrq from (SELECT t.zgh,min(wm) mwm FROM T group by t.zgh) t1,(SELECT T.WM, min(RQ) AS MRQ FROM T GROUP BY T.WM) t2 where t1.mwm =t2.WM
KEEP DENSE_RANK 减少表扫描次数,效率得到保障
SELECT ZGH, MIN(WM) KEEP(DENSE_RANK FIRST ORDER BY WM), MIN(RQ) KEEP(DENSE_RANK FIRST ORDER BY WM) FROM t GROUP BY ZGH;
正确结果如下