【问题标题】:Group values by another field按另一个字段对值进行分组
【发布时间】:2018-07-19 23:31:13
【问题描述】:

我有以下代码

ID | Name | Salary
---|------|-------
1  | Tom  | 100
2  | Tom  | 200
3  | Max  | 200
4  | Jim  | 100
5  | Max  |  50
6  | Tom  | 300
7  | Jim  | 200

我正在尝试从具有最高薪水的用户名中获取这些 ID。 预期结果:

ID | Name 
---|------
6  | Tom 
3  | Max 
7  | Jim 

我尝试过的没有成功:

SELECT ID, Name FROM Employee WHERE ID IN 
(
    SELECT ID, FROM Employee GROUP BY Salary HAVING MAX(Salary)
)

【问题讨论】:

  • 你用的是什么数据库?
  • 微软 SQL 2008

标签: sql sql-server sql-server-2008 select aggregate


【解决方案1】:

表达这个问题的一种方法是将您的Employee 表加入到一个子查询中,该子查询标识每个名字的最高薪水。

SELECT e1.ID, e1.Name
FROM Employee e1
INNER JOIN
(
    SELECT Name, MAX(Salary) AS max_salary
    FROM Employee
    GROUP BY Name
) e2
    ON e1.Name = e2.Name AND e1.Salary = e2.max_salary;

Demo

我们也可以使用相关子查询来解决这个问题:

SELECT e1.ID, e1.Name
FROM Employee e1
WHERE e1.Salary = (SELECT MAX(e2.Salary) FROM Employee e2
                   WHERE e1.Name = e2.Name);

为了完善这个答案,假设您使用的是 SQL Server 并且可以访问ROW_NUMBER,我们可以编写以下查询:

SELECT ID, Name
FROM
(
    SELECT ID, Name,
        ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Salary DESC) rn
    FROM Employee
) t
WHERE rn = 1;

【讨论】:

  • 第二种方法使用IN不是更好吗? sqlfiddle.com/#!9/ad1f1c/5
  • @Shneeg 这是编写第二个查询的一种有趣方式,据我所知,它只能在 MySQL 上运行。我相信在引擎盖下该查询将执行与使用连接的第一个查询类似。所以是的,它可能优于我上面的相关方法。
  • 如果您觉得需要更多信息,可以提出一个新问题。
【解决方案2】:

您可以使用窗口函数轻松做到这一点:

select id, name, salary, 
from (
  select id, name, salary, 
         max(salary) over () as max_salary
  from employee
) t
where salary = max_salary
order by name;

您没有说明您的 DBMS,但以上是标准 SQL。这通常比使用额外的group by 加入派生表要快

【讨论】:

  • 搞笑:我可以发誓我看到了 MySQL 标签。现在我再看一遍,我只看到 SQL。
  • @TimBiegeleisen:连 MySQL 也终于来到了 21 世纪:dev.mysql.com/doc/refman/8.0/en/window-functions.html
  • 是的,听说过。准备好开始丢失您接受的 MySQL 答案,因为巨魔开始发布窗口函数查询。
猜你喜欢
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2019-10-08
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多