【问题标题】:Get second highest salary for each person in mysql获取mysql中每个人的第二高薪水
【发布时间】:2018-06-20 15:54:36
【问题描述】:

我们有如下表格

person_id  |    salary
   1       |     1500
   1       |     1000
   1       |      500
   2       |     2000
   2       |     1000
   3       |     3000
   3       |     2000
   4       |     3000
   4       |     1000

我们希望每个人的薪水第二高。按每个人分组并获得第二高的薪水。如下所示

person_id  |    salary
   1       |     1000
   2       |     1000
   3       |     2000
   4       |     1000

提前致谢:)

【问题讨论】:

标签: mysql sql


【解决方案1】:

试试

select t1.*
from your_table t1
join
(
    select person_id,
           @rank := case when person_id = @prevPersonId then @rank + 1 else 1 end as rank,
           @prevPersonId := person_id
    from your_table
    cross join (select @rank := 0, @prevPersonId := 0) r
    group by person_id
    order by person_id asc, salary desc
) t2 on t1.person_id = t2.person_id
where rank = 2

【讨论】:

【解决方案2】:

通过使用聚合函数和自连接,您可以执行类似的操作

select a.*
from demo a
left join demo b on a.person_id = b.person_id
group by a.person_id,a.salary
having sum(a.salary < b.salary) = 1 /* 0 for highest 1 for second highest 2 for third and so on ... */

或在sum中使用完整的case表达式

having sum(case when a.salary < b.salary then 1 else 0 end)  = 1

Demo

注意这不会像一个人可能有 2 个相同的薪水值那样处理关系,我假设一个人的每个薪水值都与一个人的其他薪水值不同,以处理@juergen 提到的这种案例方法 d 将起作用带有额外的case语句

【讨论】:

  • 给你加一个,但这如何处理关系?
  • 如果一个人可以有 2 个相同的工资值,这不处理关系,让我在我的答案中添加这个
  • 随机的想法,也许如果还有第三个独特的列,我们可以将它包含在分组中,这样就会打破平局。
  • @TimBiegeleisen 是的,这听起来可能会打破关系,但不完全确定
【解决方案3】:

这是使用existshaving 子句的一种方式

SELECT person_id,
       Max(salary)
FROM   Yourtable a
WHERE  EXISTS (SELECT 1
               FROM   Yourtable b
               WHERE  a.person_id = b.person_id
               HAVING ( a.salary < Max(b.salary)
                        AND Count(*) > 1 )
                       OR Count(Distinct salary) = 1)
GROUP  BY person_id 

【讨论】:

  • 即使这样也不会返回具有相同多份薪水或只有一份薪水的 person_id 的行。
  • 没有相同的person_id 在多行中具有相同的薪水有问题。 check here pls
【解决方案4】:

JOIN 的另一种方式。

查询

 select t1.`person_id`, max(coalesce(t2.`salary`, t1.`salary_1`)) as `salary_2` from(
   select `person_id`, max(`salary`) as `salary_1`
   from `your_table_name`
   group by `person_id`
) t1
left join `your_table_name` t2
on t1.`person_id` = t2.`person_id`
and t1.`salary_1` <> t2.`salary`
group by t1.`person_id`;

Find a sql fiddle demo here

【讨论】:

    【解决方案5】:

    你也可以使用

    select max(salary), person_id
    from (select salary, person_id from demo 
          except 
          (select max(salary), person_id from demo group by person_id)) s
    group by person_id
    

    从初始数据集中删除每个人的最高工资并重新开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      • 2011-12-20
      相关资源
      最近更新 更多