sql min函数和其他列

时间:2016-11-24 19:40:31

标签: mysql sql

我想知道是否可以将另一列添加到包含聚合函数(如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

4 个答案:

答案 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_iduser_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;