纸飞机

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  22 随笔 :: 28 文章 :: 30 评论 :: 0 Trackbacks

问题:查找某个列中值的模式(数学中的模式概念就是对于给定的数据集出现最频繁的元素)。例如,查找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

使用窗口函数DENSE_RANK,把工资重复出现次数分等级,以便提取模式:

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给出的解决方案。对于Oracle9i及更高版本,可以用聚集函数MAX的KEEP扩展,以得到SAL模式。特别要注意的是,如果存在绑带,也即多个行都是模式,则采用KEEP方案仅能得到一个,即其中工资最高的那个。如果想要看所有模式(如果存在多个模式),则必须修改该方案,或者简单地使用前面介绍的DB2解决方案。在这个例子中,由于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

使用子查询查找模式:

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

内联视图X将返回每个SAL及它出现的次数。内联视图Y使用窗口函数DENSE_RANK(它允许绑带)给结果排序。结果按每个SAL出现的次数分等级,如下所示:

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

最外层的查询只简单地保留RNK为1的行。

Oracle

内联视图将返回所有SAL及其出现的次数,如下所示:

select sal, count(*) cnt

   from emp

where deptno=20

group by sal

   SAL         CNT

----- ----------

   800           1

1100           1

2975           1

3000           2

下一步,使用聚集函数MAX的KEEP扩展查找模式。如果仔细分析下面给出的KEEP子句,会发现它又有三个子句,即DENSE_RANK、FIRST和ORDER BY CNT DESC:

keep(dense_rank first order by cnt desc)

这种做法对求模式极其方便。KEEP子句根据内联视图返回的CNT值来确定MAX返回SAL的哪个值。按从右向左的方向将CNT递减排序,然后保留下按DENSE_RANK次序返回的所有CNT值的第一个值。查看一下内联视图的结果集,就会看到3000具有最高的CNT值 —— 2。MAX(SAL) 返回的是拥有最高CNT值的最大SAL,在本例中是3000。

有关Oracle中集合函数的KEEP扩展的深入讨论,请参阅第11章第11.11节。有关Oracle中集合函数的KEEP扩展的深入讨论,请参阅第11章第11.11节。

MySQL和PostgreSQL

子查询将返回每个SAL出现的次数。外层查询将返回其的出现次数大于等于子查询所返回所有计数值的SAL(换句话说,外层查询会返回DEPTNO 20中出现最多的工资)。

posted on 2008-05-14 21:44 纸飞机 阅读(314) 评论(0)  编辑  收藏 所属分类: Database

只有注册用户登录后才能发表评论。


网站导航: