我想知道是否可以将另一列添加到包含聚合函数(如min,max ...)的select语句中
示例:
SELECT user_id, MAX(salary) FROM users;
这个语句在sql标准中是正确的(在mysql中它的工作); 它在mysql中工作,但我想我在某处读到如果我在select子句中放置一个聚合函数,除了聚合函数之外我不能放任何东西,或者如果有一个group by,则分组列可以在select子句中(在mysql中)
编辑:
User(user_id, name, last_name, salary)
我想从user_id, name, (maximum salary column)
表中选择User
;没有子查询可以做到吗?
用户表
User_id, Name, Salary
| 1 | user1 | last1 | 500 | |
|---|-------|-------|------|---|
| 2 | user2 | last2 | 1000 | |
| 3 | user3 | last3 | 750 | |
| | | | | |
输出必须是user_id, username, lastname, and salary of the user who have the max salary
,所以输出必须是:
2 user2 last2 1000
答案 0 :(得分:5)
首先:不,
SELECT user_id, MAX(salary) FROM users;
不符合标准。您正在使用没有MAX
子句的聚合函数(GROUP BY
)。通过这样做,您可以告诉DBMS将所有记录聚合到一个结果行。那你告诉DBMS在这个结果行中显示什么?表格中的最高薪水(MAX(salary)
)和 user_id
。但是,没有 user_id
;表中可能有许多不同的user_id
。这违反了SQL标准。 MySQL可以自由地将非聚合的user_id
解释为任何 user_id
(任意选择)。
因此,即使查询运行,其结果通常也不是理想的结果。
此查询:
SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id;
另一方面,符合标准。让我们再看一下这个查询的作用:这次有一个GROUP BY
子句告诉DBMS你想要每个user_id
一个结果行。对于您要展示的每个user_id
: user_id
, name
和最大salary
。所有这些都是有效的表达; user_id
是user_id
本身, 名称是与user_id
关联的一个用户名,最大为{{ 1}}是用户的最高薪水。允许使用未分类的列salary
,因为它在功能上依赖于分组依据name
。但是,许多DBMS不支持这一点,因为确定表达式是否在功能上依赖于组是非常复杂的。
至于如何显示具有最高薪水的用户记录,您需要一个限制条款。 MySQL为此提供user_id
,它可以获得前n行。然而,它并没有处理关系。
LIMIT
是
SELECT * FROM users ORDER BY salary DESC LIMIT 1;
标准SQL中的。
然而,为了处理关系,如
SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY;
你需要在MySQL中使用子查询,因为SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES;
不支持这个:
LIMIT
答案 1 :(得分:2)
让我们看一个例子:
mysql> select * from users;
+---------+----------+
| user_id | salary |
+---------+----------+
| 1 | 42000.00 |
| 2 | 39000.00 |
| 3 | 50000.00 |
+---------+----------+
mysql> SELECT user_id, MAX(salary) FROM users;
+---------+-------------+
| user_id | MAX(salary) |
+---------+-------------+
| 1 | 50000.00 |
+---------+-------------+
该怎么办?用户1不是工资为50000.00的用户。
mysql> SELECT user_id, MAX(salary), MIN(SALARY) FROM users;
+---------+-------------+-------------+
| user_id | MAX(salary) | MIN(SALARY) |
+---------+-------------+-------------+
| 1 | 50000.00 | 39000.00 |
+---------+-------------+-------------+
用户1也不是39000.00的用户。这很可疑,对吧?
使用聚合函数时,它们仅适用于您使用函数的列.user_id列不会神奇地知道最大值来自哪一行,并显示相应的user_id。
在那个例子中,我查询MAX和MIN薪水。但这些属于不同的用户!应该显示哪个user_id,即使user_id可以自动来自聚合值来自的行?
如果两个用户的薪水相同,那么这与最高工资相关呢?应该显示哪个user_id?
如果您使用的聚合函数不会返回任何一行中存在的值,该怎么办?
mysql> SELECT user_id, AVG(salary) FROM users;
+---------+--------------+
| user_id | AVG(salary) |
+---------+--------------+
| 1 | 43666.666667 |
+---------+--------------+
以下是解释:在读取整组行之后,聚合函数会将结果缩减为单行。不在聚合函数内的列(如此处的user_id)从行组中的某个任意行获取其值。任意并不意味着随机实践,它往往是该组中第一个MySQL行读取。但是,并不能保证永远都是这样。
这有用吗?不是特别的。在其他数据库中,它不是有效的查询,它会逐字地生成错误。
事实上,MySQL 5.7通过强制执行不允许模糊查询的规则来改变行为。如果您尝试在MySQL 5.7上运行上面的查询,它将生成错误:
ERROR 1140(42000):在没有GROUP BY的聚合查询中,SELECT列表的表达式#1包含非聚合列" test.users.user_id&#39 ;;这与sql_mode = only_full_group_by
不兼容
可以选择使其像早期版本的MySQL一样运行。有关详细信息,请阅读:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
作为一个琐事,SQLite是另一个允许这种任意结果的数据库。仅在SQLite中,user_id的值将来自组中读取的 last 行。去图。
答案 2 :(得分:2)
根据您的需要,告诉您有不同的解决方案....
没有分组,没有子查询,简单的蛋糕
select *
from users
ORDER BY salary DESC
LIMIT 1
答案 3 :(得分:0)
尝试使用此功能:
SELECT id,
salary
FROM (SELECT id,
salary,
MAX(salary) over ([partition by] [order by] dept) mx_sal
FROM your_tbl)
WHERE salary = mx_sal;