如何从表中提取第二高的行

时间:2016-01-27 15:15:04

标签: sql oracle oracle11g greatest-n-per-group

我有四张桌子:

  1. 批处理(batch_id,batch_start_date,batch_strength,course_id)
  2. 课程(course_id,course_name,course_category,course_fees,course_duration)
  3. 注册(batch_id,student_id,enrollment_date)
  4. 学生(student_id,student_name,student_mail,student_date_of_birth,student_city,student_phone,student_qualification)
  5. 现在根据问题,我必须展示收入第二高的coursename

    根据上述问题,这是我的解决方案

    select c.course_name, c.course_fees*count(c.course_name) Total_Revenue
    from course c join(batch b join enrollment e 
    on b.batch_id=e.batch_id) 
    on c.course_id=b.course_id
    group by c.course_name, c.course_fees
    order by Total_Revenue desc ;
    

    现在问题是我无法从上面的代码中从结果表中提取第二行。如何从上面生成的表中提取第二行?(特别感谢Oracle 11g的答案)

4 个答案:

答案 0 :(得分:5)

使用row_number()

select *
from (select c.course_name, c.course_fees*count(c.course_name) as Total_Revenue,
             row_number() over (order by c.course_fees*count(c.course_name)) as seqnum
      from batch b join
           enrollment e 
           on b.batch_id = e.batch_id join
           course c
           on c.course_id=b.course_id
      group by c.course_name, c.course_fees
     ) bec
where seqnum = 2;

如果你可以先绑定并仍然想要第二名,那么请使用dense_rank()代替row_number()

答案 1 :(得分:3)

非分析解决方案只是为了它的乐趣:

with r as (
    select min(c.course_name) as course_name, min(c.course_fees) * count(*) as revenue
    from
        course c
        inner join batch b on b.course_id = c.course_id
        inner join enrollment e on e.batch_id = b.batch_id
    group by c.course_id
)
select course_name, revenue
from r
where revenue = (select max(revenue) from r where revenue < (select max(revenue) from r))

这可以处理关系(在第一和第二位)。我也会走出困境并假设你真的打算按course_id进行分组。这看起来更像是一次课堂练习,所以我不希望有任何复杂的事情,如历史费用信息或类似的事情。

修改 根据您在下面的评论,听起来您可能有多个相同名称和不同费用的课程。我怀疑您的原始查询无法正常运行,因为您还要对course_fees进行分组。

请注意,以下更改使用course_name上的分组和course_fees上的总和:

with r as (
    select course_name, sum(c.course_fees) as revenue
    from
        course c
        inner join batch b on b.course_id = c.course_id
        inner join enrollment e on e.batch_id = b.batch_id
    group by c.course_name
)
select course_name, revenue
from r
where revenue = (select max(revenue) from r where revenue < (select max(revenue) from r))

答案 2 :(得分:0)

最简单的方法是使用oracle rownum。

Oracle正在为每一行保存一个唯一的id,因此您无需操纵数据或使用任何分析函数

select * from (
    select c.course_name, c.course_fees*count(c.course_name) Total_Revenue
    from batch b 
    join enrollment e on(b.batch_id=e.batch_id)
    join course c on(c.course_id=b.course_id)
    group by c.course_name, c.course_fees
    order by Total_Revenue desc)
where rownum = 2 ;

答案 3 :(得分:0)

您还可以创建自己的聚合函数。 Oracle docs提到函数SecondMax作为示例。但是如果有一个合适的索引,那么row_numer函数可能会提供更好的执行计划。