评论区里的答案详解

获取当前薪水第二多的员工的emp_no以及其对应的薪水salary,不准使用order by

http://www.nowcoder.com/questionTerminal/c1472daba75d4635b7f8540b837cc719

评论区里的答案详解:

-- 方法一
select s.emp_no, s.salary, e.last_name, e.first_name
from salaries s join employees e
on s.emp_no = e.emp_no
where s.salary =              -- 第三步: 将第二高工资作为查询条件
    (
    select max(salary)        -- 第二步: 查出除了原表最高工资以外的最高工资(第二高工资)
    from salaries
    where salary <    
        (
        select max(salary)    -- 第一步: 查出原表最高工资
        from salaries
        where to_date = '9999-01-01'   
        )
    and to_date = '9999-01-01'
    )
and s.to_date = '9999-01-01'



-- 方法二
select s.emp_no, s.salary, e.last_name, e.first_name
from salaries s join employees e
on s.emp_no = e.emp_no
where s.salary =
    (
    select s1.salary
    from salaries s1 join salaries s2      -- 自连接查询
    on s1.salary <= s2.salary
    group by s1.salary                     -- 当s1<=s2链接并以s1.salary分组时一个s1会对应多个s2
    having count(distinct s2.salary) = 2   -- (去重之后的数量就是对应的名次)
    and s1.to_date = '9999-01-01'
    and s2.to_date = '9999-01-01'
    )
and s.to_date = '9999-01-01'

表自连接以后:

s1 s2
100 100
98 98
98 98
95 95

s1<=s2链接并以s1.salary分组时一个s1会对应多个s2

s1 s2
100 100
98 100
98
98
95 100
98
98
95

对s2进行去重统计数量, 就是s1对应的排名

全部评论
为啥要加上where to_date='9999-01-01'这个条件呢?
2 回复 分享
发布于 2021-06-06 18:57
为什么s1<=s2不是s1>=s2
2 回复 分享
发布于 2020-11-17 16:14
用了第一种,从原表中先剔除原表中MAX(salary)及对应emp_no,构建一个临时的表,再在当前临时表求MAX
1 回复 分享
发布于 2021-07-17 10:24
想问一下,where不是不能和聚合函数一起用吗
1 回复 分享
发布于 2020-12-22 18:12
方法二运行失败的,实测对时间的约束必须放到 JOIN ON 后面,让 HAVING 语句到最后。
13 回复 分享
发布于 2021-01-18 22:06
to_date的作用是保证当前员工,在实际生产中,如果to_date不是'9999-01-01'或者to_date在当前日期前,说明该员工已经离职。(不要为了做题而做题)
11 回复 分享
发布于 2021-05-07 20:34
理解了第二种方法之后才感到其中的精妙,太赞了!!解释一下:如果工资是最大数,那么只有1个数会大于等于最大数,那就是最大数本身。以此类推,如果是第二大数,那么会有2个不同的数字大于等于第二大数,所以count(distinct s2.salary) = 2 在告诉我们有2个不同数字大于等于这个工资,那这个工资就是第二高了。
7 回复 分享
发布于 2022-09-17 04:48 美国
太帅了,赞~~~
5 回复 分享
发布于 2020-10-18 12:01
时间的意义有什么作用吗,to_date 大家都一样啊。请教一下
3 回复 分享
发布于 2021-03-26 12:12
第二个是哪位神人想出来的解法,把连接查询运用到炉火纯青
2 回复 分享
发布于 2023-03-12 16:31 江苏
这嵌套逻辑。。王者啊!反正我还想不到
2 回复 分享
发布于 2022-01-02 02:18
想问一下大佬们,为啥一定要加to_date = '9999-01-01'
1 回复 分享
发布于 2023-09-03 19:00 湖南
我想到了方法一,但是暂时还没看懂方法二
1 回复 分享
发布于 2022-04-10 19:26
to_date有什么用? 不加也可通过啊
1 回复 分享
发布于 2021-03-29 21:04
select s.emp_no, max(s.salary), e.last_name, e.first_name FROM salaries s JOIN employees e ON s.emp_no = e.emp_no where s.salary <(select max(salary) FROM salaries and to_date = '9999-01-01') and s.to_date = '9999-01-01',请问这样写为什么不行?
1 回复 分享
发布于 2020-11-09 14:17
厉害的~看到好多人都是用这两种方法来做,我的方法和方法二类似,但是稍微简化了一点,感兴趣的可以参考一下: SELECT c.emp_no,c.salary,d.last_name,d.first_name FROM (SELECT a.emp_no,MIN(a.salary) AS 'salary' FROM salaries a JOIN salaries b ON a.salary <= b.salary WHERE a.to_date = '9999-01-01' AND b.to_date = '9999-01-01' GROUP BY a.emp_no HAVING COUNT(b.emp_no) = 2)c LEFT OUTER JOIN employees d ON c.emp_no = d.emp_no;
1 回复 分享
发布于 2020-10-19 15:31
崇拜,献上我的膝盖
点赞 回复 分享
发布于 2024-11-27 17:59 上海
第二种方法为啥会报错呢? 程序异常退出, 请检查代码"是否有数组越界等异常"或者"是否有语法错误" SQL_ERROR_INFO: "Unknown column 's1.to_date' in 'having clause'" 可以解答一下吗?
点赞 回复 分享
发布于 2024-09-25 14:40 辽宁
我这木鱼脑袋只能理解第一种方法
点赞 回复 分享
发布于 2024-03-01 17:06 四川
order by 为什么不能使用?是有什么底层逻辑吗
点赞 回复 分享
发布于 2023-09-07 14:45 湖南

相关推荐

03-21 08:46
已编辑
门头沟学院 C++
一个什么都不会的学生:当你有硕士学历的时候HR会说就是比本科生强
点赞 评论 收藏
分享
评论
449
69
分享

创作者周榜

更多
牛客网
牛客企业服务