MYSQL查询查找具有第n个最高薪水的所有员工

时间:2014-07-31 11:49:10

标签: mysql sql greatest-n-per-group

这两个表是salary_employee和employee

employee_salary

salary_id  emp_id  salary

员工

emp_id |    first_name | last_name |    gender  | email | mobile  | dept_id  | is_active

查询以获得n个最高工资的所有员工,其中n = 1,2,3,...任意整数

SELECT  a.salary, b.first_name 
FROM    employee_salary a 
JOIN    employee b 
ON      a.emp_id = b.emp_id 
WHERE   a.salary = (
                      SELECT    salary 
                      FROM      employee_salary  
                      GROUP BY  salary 
                      DESC     
                      LIMIT 1 OFFSET N-1
                   )

我的问题:

1)有没有更好的和优化的方式我们可以查询,


2)使用LIMIT是一个不错的选择


3)我们有更多的选择来计算第n个最高薪水,这是最好的,什么可以跟随,什么时候?

使用的一个选项:

SELECT *
   FROM employee_salary t1
   WHERE ( N ) = ( SELECT COUNT( t2.salary )
                   FROM employee_salary t2 
                   WHERE  t2.salary >=  t1.salary 
                 )

使用排名方法

SELECT salary
FROM
(
  SELECT @rn := @rn + 1 rn,
       a.salary
  FROM tableName a, (SELECT @rn := 0) b
  GROUP BY salary DESC
) sub
WHERE sub.rn = N

4 个答案:

答案 0 :(得分:3)

评论太长了。

您已经问过似乎是一个合理的问题。在SQL中有不同的处理方式,有时候某些方法比其他方法更好。排名问题只是许多例子中的一个。 "答案"你的问题是,一般来说,order by在MySQL中的表现要优于group by。虽然这取决于特定的数据以及您认为的更好的"。

问题的具体问题是你有三个不同的查询返回三个不同的东西。

第一个返回所有员工的密集等级"那是一样的。该术语是故意使用的,因为它对应于MySQL不支持的ANSI dense_rank()函数。因此,如果您的工资是100,100和10,它将返回两行,排名为1,一行排名为2.

如果存在关系,则第二个返回不同的结果。如果工资是100,100,10,则此版本将不返回排名为1的行,排名为2的两行,以及排名为3的一行。

第三个返回一个完全不同的结果集,这只是工资的薪水和排名。

我的评论旨在尝试对您的数据进行查询。事实上,你应该从功能和性能的角度来决定你真正想要的东西。

答案 1 :(得分:1)

LIMIT要求SQL浏览0到N之间的所有记录,因此需要增加您想要查看的排名的后续时间。但是,IMO认为这个问题无法更好地解决。

  • 正如Gordon Linoff所建议的那样:使用常用的排名运行您的选项(通常使用哪些排名,哪些排名不是?结果可能在排名1上快,但在排名100上可怕)。

  • 执行并分析Query Execution Plan并相应地创建索引(例如在薪水栏上)并重新测试您的查询。

其他选择:

选项4:

您可以构建一个用作缓存的排名表。您的Limit-Query的执行计划显示(see sqlfiddle here),mysql已经创建了一个临时表来解决查询。

优点:简单快捷 缺点:强制您在每次数据更改时重新生成排名表

选项5:

您可以重新考虑如何定义" rank"。 如果我们有以下工资:

  1. 100' 000
  2. 100' 000
  3. 80' 000
  4. 员工Nr 3是否被认为是3级或2级? 1和2是同一等级(等级1),但3是等级3?

    如果您定义rank = order,则可以大大简化查询

    SELECT a.salary,b.first_name FROM employee_salary a,员工b WHERE a.emp_id = b.emp_id 按薪水排序 限制1 OFFSET 4

    演示:http://sqlfiddle.com/#!2/e7321d/1/0

答案 2 :(得分:0)

试试这个,

SELECT * FROM one as A WHERE ( n ) = ( SELECT COUNT(DISTINCT(b.salary)) FROM one as B  WHERE 
B.salary >= A.salary )

答案 3 :(得分:0)

假设emp_salary表具有以下记录:

Employee salary table

并且您希望选择所有员工,其中nth(N = 1,2,3等)最高/最低(仅更改>(最高),<(最低)运营商根据您的需要)薪水,使用下面的sql:

SELECT DISTINCT(a.salary), 
       a.id, 
       a.name 
       FROM emp_salary a 
       WHERE N = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b
                  WHERE b.salary >= a.salary 
                 );

例如,如果要选择薪水第二高的所有员工,请使用以下sql:

 SELECT DISTINCT(a.salary), 
       a.id, 
       a.name 
       FROM emp_salary a 
       WHERE 2 = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b
                  WHERE b.salary >= a.salary 
                 );

2nd highest salary list

但是如果你想只显示第二高的薪水(只有一个记录),请使用下面的sql:

SELECT DISTINCT(a.salary), 
       a.id, 
       a.name 
       FROM emp_salary a 
       WHERE 2 = (SELECT COUNT( DISTINCT(b.salary)) FROM emp_salary b
                  WHERE b.salary >= a.salary 
                 ) limit 1;

2nd-highest-salary(single record-not-duplicate)