Mysql SQL排序不遵循group by语句,始终使用主键

Mysql SQL排序不遵循group by语句,始终使用主键,mysql,sql,sorting,select,greatest-n-per-group,Mysql,Sql,Sorting,Select,Greatest N Per Group,我有一个SQL数据库,其中有一个名为staff的表,表中有以下列: workerID (Prim.key), name, department, salary 我应该找到每个部门工资最高的员工,并使用以下声明: select staff.workerID, staff.name, staff.department, max(staff.salary) AS biggest from staff group by staff.department 我从每个部门都会看到一名员工,但他们不是工资最

我有一个SQL数据库,其中有一个名为staff的表,表中有以下列:

workerID (Prim.key), name, department, salary
我应该找到每个部门工资最高的员工,并使用以下声明:

select staff.workerID, staff.name, staff.department, max(staff.salary) AS biggest
from staff
group by staff.department
我从每个部门都会看到一名员工,但他们不是工资最高的员工,而是显示了最高的工资值,即使该员工没有获得该工资

显示的人员是每个部门员工ID最低的员工

因此,尽管GROUPBY语句中没有提到主键,但仍使用主键进行排序

有人能解释一下,到底发生了什么,可能还有如何正确排序

试试这个:

SELECT s.workerID, s.name, s.department, s.salary
FROM staff s 
INNER JOIN (SELECT s.department, MAX(s.salary) AS biggest 
            FROM staff s GROUP BY s.department
          ) AS B ON s.department = B.department AND s.salary = B.biggest;

对正在发生的事情的解释:

您正在staff.department上执行分组依据,但是您的选择列表包含两个非分组列staff.workerID和staff.name。在标准sql中,这是一个语法错误,但是MySql允许这样做,因此查询编写者必须确保他们自己处理这种情况

参考:

在标准SQL中,包含GROUP BY子句的查询不能引用select列表中未在GROUP BY子句中命名的未聚合列

MySQL扩展了GROUPBY的使用,因此select列表可以引用GROUPBY子句中未命名的未聚合列

服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的

从MySQL 5.1开始,可以通过在sql_模式下设置ONLY_FULL_GROUP_by标志来禁用非标准功能:

如何修复:

在内部查询中,使用GROUP BY获取部门及其最高工资。然后在外部查询中,将这些结果与主表连接起来,主表将为您提供所需的结果。

这是通常的情况,使用聚合函数的group by不能保证与聚合函数对应的正确行。现在有很多方法可以做到这一点,通常的做法是子查询和连接。但是,如果表很大,那么从性能角度来看,它会导致死亡,因此另一种方法是使用左连接

假设我们有桌子

+----------+------+-------------+--------+
| workerid | name | department  | salary |
+----------+------+-------------+--------+
|        1 | abc  | computer    |    400 |
|        2 | cdf  | electronics |    200 |
|        3 | gfd  | computer    |    400 |
|        4 | wer  | physics     |    300 |
|        5 | hgt  | computer    |    700 |
|        6 | juy  | electronics |    100 |
|        7 | wer  | physics     |    400 |
|        8 | qwe  | computer    |    200 |
|        9 | iop  | electronics |    800 |
|       10 | kli  | physics     |    800 |
|       11 | qsq  | computer    |    600 |
|       12 | asd  | electronics |    300 |
+----------+------+-------------+--------+
因此,我们可以得到如下数据:

select st.* from staff st
left join staff st1 on st1.department = st.department
and st.salary < st1.salary
where 
st1.workerid is null

我最喜欢的解决方案是使用左连接:


此查询从其部门中选择薪资最高的所有员工;i、 e.如果两个或两个以上的员工的工资相同,且其所在部门的工资较高,则会选择所有这些员工。

在使用GROUP BY进行查询时,SELECT子句中出现的字段必须同时出现在GROUP BY子句中,或作为聚合函数MIN、MAX、SUM、COUNT的参数出现。如果它们不适合这两种情况,则它们在结果集中的值为。查询中的staff.workerID和staff.name就是这种情况。请这样考虑:如果从查询中删除MAXstaff.salary列,则结果中的其余列不应更改其值。MySQL在这种情况下应该选择工资最高的员工吗?为什么-
+----------+------+-------------+--------+
| workerid | name | department  | salary |
+----------+------+-------------+--------+
|        1 | abc  | computer    |    400 |
|        2 | cdf  | electronics |    200 |
|        3 | gfd  | computer    |    400 |
|        4 | wer  | physics     |    300 |
|        5 | hgt  | computer    |    700 |
|        6 | juy  | electronics |    100 |
|        7 | wer  | physics     |    400 |
|        8 | qwe  | computer    |    200 |
|        9 | iop  | electronics |    800 |
|       10 | kli  | physics     |    800 |
|       11 | qsq  | computer    |    600 |
|       12 | asd  | electronics |    300 |
+----------+------+-------------+--------+
select st.* from staff st
left join staff st1 on st1.department = st.department
and st.salary < st1.salary
where 
st1.workerid is null
+----------+------+-------------+--------+
| workerid | name | department  | salary |
+----------+------+-------------+--------+
|        5 | hgt  | computer    |    700 |
|        9 | iop  | electronics |    800 |
|       10 | kli  | physics     |    800 |
+----------+------+-------------+--------+
SELECT m.workerID, m.name, m.department, m.salary
FROM staff m             # 'm' from 'maximum'
    LEFT JOIN staff o    # 'o' from 'other'
        ON m.department = o.department    # match rows by department
        AND m.salary < o.salary           # match each row in `m` with the rows from `o` having bigger salary
WHERE o.salary IS NULL       # no bigger salary exists in `o`, i.e. `m`.`salary` is the maximum of its dept.
;