問(wèn)題:查找某個(gè)列中值的模式(數(shù)學(xué)中的模式概念就是對(duì)于給定的數(shù)據(jù)集出現(xiàn)最頻繁的元素)。例如,查找DEPTNO 20中工資的模式。例如下列工資:
select sal
from emp
where deptno = 20
order by sal
SAL
----------
800
1100
2975
3000
3000
the mode is 3000.
解決方案
DB2和SQL Server
使用窗口函數(shù)DENSE_RANK,把工資重復(fù)出現(xiàn)次數(shù)分等級(jí),以便提取模式:
1 select sal
2 from (
3 select sal,
4 dense_rank()over(order by cnt desc) as rnk
5 from (
6 select sal, count(*) as cnt
8 from emp
9 where deptno = 20
10 group by sal
11 ) x
12 ) y
13 where rnk = 1
Oracle
在Oracle8i Database中,可以使用DB2給出的解決方案。對(duì)于Oracle9i及更高版本,可以用聚集函數(shù)MAX的KEEP擴(kuò)展,以得到SAL模式。特別要注意的是,如果存在綁帶,也即多個(gè)行都是模式,則采用KEEP方案僅能得到一個(gè),即其中工資最高的那個(gè)。如果想要看所有模式(如果存在多個(gè)模式),則必須修改該方案,或者簡(jiǎn)單地使用前面介紹的DB2解決方案。在這個(gè)例子中,由于3000是DEPTNO 20中SAL的模式,而且它也是最高的SAL,因此以下方案就可以了:
1 select max(sal)
2 keep(dense_rank first order by cnt desc) sal
3 from (
4 select sal, count(*) cnt
5 from emp
6 where deptno=20
7 group by sal
8 )
MySQL和PostgreSQL
使用子查詢(xún)查找模式:
1 select sal
2 from emp
3 where deptno = 20
4 group by sal
5 having count(*) >= all ( select count(*)
6 from emp
7 where deptno = 20
8 group by sal )
討論
DB2和SQL Server
內(nèi)聯(lián)視圖X將返回每個(gè)SAL及它出現(xiàn)的次數(shù)。內(nèi)聯(lián)視圖Y使用窗口函數(shù)DENSE_RANK(它允許綁帶)給結(jié)果排序。結(jié)果按每個(gè)SAL出現(xiàn)的次數(shù)分等級(jí),如下所示:
1 select sal,
2 dense_rank()over(order by cnt desc) as rnk
3 from (
4 select sal,count(*) as cnt
5 from emp
6 where deptno = 20
7 group by sal
8 ) x
SAL RNK
----- ----------
3000 1
800 2
1100 2
2975 2
最外層的查詢(xún)只簡(jiǎn)單地保留RNK為1的行。
Oracle
內(nèi)聯(lián)視圖將返回所有SAL及其出現(xiàn)的次數(shù),如下所示:
select sal, count(*) cnt
from emp
where deptno=20
group by sal
SAL CNT
----- ----------
800 1
1100 1
2975 1
3000 2
下一步,使用聚集函數(shù)MAX的KEEP擴(kuò)展查找模式。如果仔細(xì)分析下面給出的KEEP子句,會(huì)發(fā)現(xiàn)它又有三個(gè)子句,即DENSE_RANK、FIRST和ORDER BY CNT DESC:
keep(dense_rank first order by cnt desc)
這種做法對(duì)求模式極其方便。KEEP子句根據(jù)內(nèi)聯(lián)視圖返回的CNT值來(lái)確定MAX返回SAL的哪個(gè)值。按從右向左的方向?qū)NT遞減排序,然后保留下按DENSE_RANK次序返回的所有CNT值的第一個(gè)值。查看一下內(nèi)聯(lián)視圖的結(jié)果集,就會(huì)看到3000具有最高的CNT值 —— 2。MAX(SAL) 返回的是擁有最高CNT值的最大SAL,在本例中是3000。
有關(guān)Oracle中集合函數(shù)的KEEP擴(kuò)展的深入討論,請(qǐng)參閱第11章第11.11節(jié)。有關(guān)Oracle中集合函數(shù)的KEEP擴(kuò)展的深入討論,請(qǐng)參閱第11章第11.11節(jié)。
MySQL和PostgreSQL
子查詢(xún)將返回每個(gè)SAL出現(xiàn)的次數(shù)。外層查詢(xún)將返回其的出現(xiàn)次數(shù)大于等于子查詢(xún)所返回所有計(jì)數(shù)值的SAL(換句話說(shuō),外層查詢(xún)會(huì)返回DEPTNO 20中出現(xiàn)最多的工資)。