如何从表中提取第二高行[重复]
Posted
技术标签:
【中文标题】如何从表中提取第二高行[重复]【英文标题】:How to extract second highest row from a table [duplicate] 【发布时间】:2016-01-27 15:15:03 【问题描述】:我有四张桌子:
-
批次(batch_id,batch_start_date,batch_strength,course_id)
课程(course_id、course_name、course_category、course_fees、course_duration)
注册(batch_id、student_id、注册日期)
学生(student_id、student_name、student_mail、student_date_of_birth、student_city、student_phone、student_qualification)
现在根据问题,我必须显示收入第二高的课程名称
根据上面的问题,这里是我的解决方案
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 的答案)
【问题讨论】:
【参考方案1】:使用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()
。
【讨论】:
@sagi 但 Gordon 指出,对于 tie 的情况,它也可以轻松更改为dense_rank()
,更不用说这是一种可移植的方法。
@sagi 你不能使用 rownum 除非你返回 1 和所需行号之间的每一行。请改用row_number
或dense_rank
分析函数【参考方案2】:
非解析解只是为了好玩:
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))
【讨论】:
我打算在这里按 course_name 分组,因为 course_id 在这里无关紧要,不会产生正确的结果 @user5451270course_id
似乎是您的主键。通常,您不希望按名称值分组。虽然我认为这里所有的课程名称都是独一无二的,但我认为这是一个坏习惯(除非你真的需要),并且在课堂之外使用主键可能对数据库引擎更有效率。如果您不介意分享,我很好奇它如何不能给出正确的结果。
当我按course_id
分组时,它不会像我预期的那样计算总收入。例如,就像在course_name
下一样,2 sql server
显示为单独的收入9000
和 7000
而我只希望 1 sql server
显示为收入为16000
并且没有course_name
列不是唯一的跨度>
@user5451270 我希望你能看看我的编辑。但是,如果您确实有多个课程行具有相同的名称和不同的费用,那么您原始查询中的分组是不正确的。
你确定我会查看你的编辑并尝试找出我是否有任何错误【参考方案3】:
您还可以创建自己的聚合函数。 Oracle docs 以函数 SecondMax 为例。但是如果有合适的索引,那么 row_numer 函数可能会给出更好的执行计划。
【讨论】:
以上是关于如何从表中提取第二高行[重复]的主要内容,如果未能解决你的问题,请参考以下文章