【问题标题】:sql min function and other columnsql min 函数和其他列
【发布时间】:2017-04-09 04:19:34
【问题描述】:

我想知道是否可以在包含聚合函数(如 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 表中选择user_id, name, (maximum salary column);没有子查询可以做到吗?

用户表

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

【问题讨论】:

  • 取决于你想做什么,mysql在聚合函数和分组方面不遵循ansi标准,所以你可以做一些其他数据库不允许的快捷方式。
  • @scaisEdge 我使用 group by,它将返回每个元组 user_id 的 max(salary),名称与使用 SELECT user_id, name, salary 相同
  • 顺便说一句,您应该向我们展示示例数据和预期输出。根据您的需要,这个问题可能会有所不同。

标签: mysql sql


【解决方案1】:

开头:不,

SELECT user_id, MAX(salary) FROM users;

不符合标准。您正在使用没有 GROUP BY 子句的聚合函数 (MAX)。通过这样做,您告诉 DBMS 将所有记录聚合到一个结果行。现在你告诉 DBMS 在这个结果行中显示什么?在表中找到的最高薪水 (MAX(salary)) 和 the user_id。但是,没有user_id;表中可能有许多不同的user_id。这违反了 SQL 标准。 MySQL 随意将非聚合的 user_id 解释为 any user_id(任意选择)。

因此,即使查询运行,它的结果通常也不是想要的。

这个查询:

SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id;

另一方面是符合标准的。让我们再看看这个查询做了什么:这次有一个GROUP BY 子句告诉DBMS 你希望每个user_id 有一个结果行。对于您要显示的每个 user_idthe user_idthe name 和最大 salary。所有这些都是有效的表达方式; user_iduser_id 本身, name 是与user_id 关联的一个用户名,最大salary 是用户的最高薪水.允许使用未聚合的列 name,因为它在功能上依赖于分组依据 user_id。但是,许多 DBMS 不支持这一点,因为要确定一个表达式在功能上是否依赖于组会变得非常复杂。

至于如何显示最高工资的用户记录,你需要一个限制子句。 MySQL 为此提供了LIMIT,它可以获得前n 行。但是它不处理关系。

SELECT * FROM users ORDER BY salary DESC LIMIT 1;

SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY;

在标准 SQL 中。

然而,为了处理关系,就像在

SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES;

你需要在 MySQL 中创建一个子查询,因为LIMIT 不支持这个:

SELECT * FROM users WHERE salary = (SELECT MAX(salary) FROM users);

【讨论】:

    【解决方案2】:

    告诉你有不同的解决方案取决于你想要什么......

    没有分组,没有子查询,Easy cake

    select * 
    from users
    ORDER BY salary DESC
    LIMIT 1
    

    【讨论】:

    • 即使我得到了接受的答案,我也忽略了关系案例@ThorstenKettner 解决方案句柄
    【解决方案3】:

    我们来看一个例子:

    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 上运行上述查询,则会产生错误:

    错误 1140 (42000):在没有 GROUP BY 的聚合查询中,SELECT 列表的表达式 #1 包含非聚合列“test.users.user_id”;这与 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 行。去图吧。

    【讨论】:

    • 感谢您的宝贵回答,但是您能给我一个解决这个问题的方法吗?
    • 我非常喜欢这个解释。查询中未聚合的 user_id 的误解再明显不过了。
    • @karim,Juan Carlos 给出了最简单的解决方案。
    【解决方案4】:

    尝试使用这个:

    SELECT id,
           salary
      FROM (SELECT id,
                   salary,
                   MAX(salary) over ([partition by] [order by] dept) mx_sal
              FROM your_tbl)
     WHERE salary = mx_sal;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-08
      • 2017-08-06
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 2012-07-07
      • 1970-01-01
      相关资源
      最近更新 更多