CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
(图)邪恶的韩国UMPC 使用 Java 编写数据库应用新规范
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Oracle >  开发

分组排序后,查询出指定条记录数,请教!

楼主nanci(☆精灵☆)2005-01-04 22:50:04 在 Oracle / 开发 提问

有表salary  
  employerid   char;  
  salary           int;  
   
  现在要求查出每组employerid中最大的前三条salary(重复的当成多条);  
  比如  
  employerid       salary  
  1                           2000  
  1                           3000  
  1                           4000  
  1                           4000  
  2                           2000  
  2                           3000  
  2                           4000  
  2                           5000  
   
  要求结果:  
  employerid       salary1     salary2     salary3    
  1                           4000           4000           3000  
  2                           5000           4000           3000  
   
  原表索引在employerid上,数据非常多(几百万条)  
  存储过程也可以,但要求很高的效率。 问题点数:100、回复次数:16Top

1 楼ATGC(花开蝶舞,木秀鸟栖)回复于 2005-01-04 23:32:20 得分 0

SQL>   select   *   from   aa;  
   
  EMPLO           SALARY  
  -----   ----------  
  1                       2000  
  1                       3000  
  1                       4000  
  1                       4000  
  2                       2000  
  2                       3000  
  2                       4000  
  2                       5000  
   
  已选择8行。  
   
  select   employerid,sum(salary1)   salary1,sum(salary2)   salary2,sum(salary3)   salary3   from(  
  select   employerid,decode('1',top3,salary,'')   salary1,decode('2',top3,salary,'')   salary2,decode('3',top3,salary,'')   salary3  
  from(  
  select   b.employerid,b.salary,top3   from(  
  SELECT   employerid,salary,  
    row_number()  
    OVER   (PARTITION   BY   employerid  
                ORDER   BY   salary   desc   NULLS   LAST)   top3  
  FROM   aa)   b  
  where   b.top3<=3))    
  group   by   employerid;  
   
  EMPLO         SALARY1         SALARY2         SALARY3  
  -----   ----------   ----------   ----------  
  1                       4000               4000               3000  
  2                       5000               4000               3000  
   
  SQL>Top

2 楼ATGC(花开蝶舞,木秀鸟栖)回复于 2005-01-04 23:39:54 得分 60

刚才随便写的,效率不太好,下面的好一些  
  select   employerid,  
      max(decode(top3,1,salary,null))   salary1,  
      max(decode(top3,2,salary,null))   salary2,  
      max(decode(top3,3,salary,null))   salary3  
  from   (select   employerid,salary,  
              row_number()  
              over   (partition   by   employerid  
                          order   by   salary   desc   nulls   last)   top3  
              from   aa)  
  where   top3<=3  
  group   by   employerid  
  /  
   
  EMPLO         SALARY1         SALARY2         SALARY3  
  -----   ----------   ----------   ----------  
  1                       4000               4000               3000  
  2                       5000               4000               3000  
  Top

3 楼qiaozhiwei(乔)回复于 2005-01-05 09:27:34 得分 0

ATGC(想到南极去看看飞翔的海鸥)的可以Top

4 楼GerryYang(轻尘)回复于 2005-01-05 09:46:55 得分 0

ATGC(想到南极去看看飞翔的海鸥)的可以,  
  employerid如果有索引的话,那应该不会慢.Top

5 楼liuyi8903(不让疑问伴随)回复于 2005-01-05 10:20:24 得分 0

不错!支持一下!Top

6 楼NinGoo(http://www.NinGoo.net)回复于 2005-01-05 10:35:44 得分 0

学习Top

7 楼NinGoo(http://www.NinGoo.net)回复于 2005-01-05 10:55:50 得分 0

顺便问一下,oracle里取两个数相除的余数该怎么做?找了半天也没找到模运算符Top

8 楼jgyun(小将)回复于 2005-01-05 11:00:04 得分 0

支持!Top

9 楼ORARichard(没钱的日子......)回复于 2005-01-05 11:11:30 得分 0

mod(a,b)Top

10 楼NinGoo(http://www.NinGoo.net)回复于 2005-01-05 11:23:01 得分 0

谢谢。呵呵,在Toad里mod不显亮,我还以为不是,晕  
   
  这题在sql   server版见过,不过sql   server   2000里不能用row_number(),所以我一下子就想到下面的写法,呵呵  
   
  select   employerid,max(decode('1',mod(rownum,3),salary,''))   salary1,  
        max(decode('2',mod(rownum,3),salary,''))   salary2,  
  max(decode('0',mod(rownum,3),salary,''))   salary3  
  from  
  (  
  select   employerid,salary     from   t1   a   where     (select   count(1)   from   t1   where   employerid=a.employerid)>=3  
                          and   (select   count(1)   from   t1   where   employerid=a.employerid   and   salary>a.salary   )<3  
  )  
  group   by   employerid  
   
  在网上找了找,还是row_number()的效率高,多学一招,开心~~~~~~~~~  
  用oracle写sql写的太少,很多都不知道,还不知道到哪里查。不知道oracle有没有sql   server一样的联机帮助可以查语法的东东,各位大侠推荐一下Top

11 楼topikachu(皮皮)回复于 2005-01-06 13:28:27 得分 40

row_number()效率太低了  
  可以先用rank()找出小范围的纪录  
  然后再用row_number  
  select   employerid   ,salary,top3   from(  
  select   employerid   ,salary,row_number()over   (partition   by   employerid   order   by   rank3   )     top3  
  from   (  
  select   employerid   ,salary,rank3   from(  
  select   employerid   ,salary,rank()over(partition   by   employerid   order   by   salary   desc)   as   rank3   from   xxx)  
    where   rank3<=3  
    )  
    )    
    where   top3<=3  
   
  外面再用decode嵌一层就完成要求了  
   
  测试用10w条纪录,oracle9i,ibm   t30笔记本  
  employerid   1-10  
  每个employerid   的salary   1-10000  
   
  employerid   ,salary建索引  
   
  用atgc的查询费时54秒  
  用我的查询费时6秒Top

12 楼ATGC(花开蝶舞,木秀鸟栖)回复于 2005-01-06 20:13:45 得分 0

奇怪呢,好像楼主没有出现过,也不来讨论讨论。。Top

13 楼baojianjun(包子)回复于 2005-01-08 13:26:12 得分 0

哈哈   ,   海鸥你耐心等等吧,  
  樓主或許在忙呢Top

14 楼ATGC(花开蝶舞,木秀鸟栖)回复于 2005-01-08 15:53:03 得分 0

等不及啊,俺要等楼主给分买米下锅呢~~~Top

15 楼charmgjj(杰)回复于 2005-01-08 21:57:13 得分 0

值得学习Top

16 楼nanci(☆精灵☆)回复于 2005-01-16 13:14:36 得分 0

实在是报谦,前阵子太忙了。。。  
   
  感谢ATGC(想到南极去看看飞翔的海鸥)   。。。  
   
  不过rank的速度的确要快些,感谢topikachu(皮皮)   。。。  
  Top

相关问题

  • 请问ejb中查询记录的传递和排序问题??
  • 如果实现查询排序后某个记录所在的记录行
  • 当查询记录为空记录集时,查询语句中的定义排序问题
  • 怎样查询指定行范围的记录
  • 删除指定范围内记录的查询
  • 数据库查询的问题:仅查询指定条数记录
  • 请问:在SQL查询时怎么才返回指定数量的记录数
  • 怎么编写查询指定字段还没有输入数据的记录
  • 一个查询命令的问题:如何查询,,指定的多行记录???无ID号....
  • 如何在adoQuery中增加一个计算字段,来显示查询出的记录的排序的号?记录一显示1,记录二显示2....

关键词

  • top
  • employerid
  • salary
  • top3
  • decode
  • aa
  • sum
  • max
  • select
  • nulls

得分解答快速导航

  • 帖主:nanci
  • ATGC
  • topikachu

相关链接

  • Oracle类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
惹火投票。。火热进行中...

社区焦点:

教你怎样用C#搞笑整人
最懒惰的程序员写的Cache
程序员如何掌握专业英语
Java栈与堆
分享:让人懊恼的面试
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo