【问题标题】:Extra Fields with SQL MIN() & GROUP BY带有 SQL MIN() 和 GROUP BY 的额外字段
【发布时间】:2010-10-17 21:46:23
【问题描述】:

当使用 SQL MIN() 函数以及 GROUP BY 时,任何其他列(不是 MIN 列或 GROUP BY 列之一)是否会与匹配的 MIN 行中的数据匹配?

例如,给定一个包含部门名称、员工名称和薪水的表:

SELECT MIN(e.salary), e.* FROM employee e GROUP BY department

显然我会得到两个不错的列,最低工资和部门。员工姓名(和任何其他员工字段)是否来自同一行?即具有 MIN(salary) 的行?

我知道很可能有两个员工的薪水相同(并且最低),但我(现在)关心的只是获取有关(或一个)的所有信息最便宜的员工。

这会选择最便宜的推销员吗?

SELECT min(salary), e.* FROM employee e WHERE department = 'sales'

基本上,我能否确定与 MIN() 函数一起返回的数据将与具有该最小值的(或单个)记录相匹配?

如果数据库很重要,我正在使用 MySql。

【问题讨论】:

    标签: sql mysql aggregate-functions


    【解决方案1】:

    另一种方法是使用分析函数。这是使用分析和 ROW_NUM 函数的查询

    select first_name,salary from (select first_name,salary, Row_NUMBER() over (PARTITION BY DEPARTMENT_ID ORDER BY Salary ASC) as row_count from employees) where row_count=1;

    【讨论】:

      【解决方案2】:

      最快的解决方案:

      SET @dep := '';
      SELECT * FROM (
        SELECT * FROM `employee` ORDER BY `department`, `salary`
      ) AS t WHERE IF ( @dep = t.`department`, FALSE, ( @dep := t.`department` ) OR TRUE );
      

      【讨论】:

        【解决方案3】:
        SELECT  e.*
        FROM    employee e
        WHERE   e.id =
                (
                SELECT  id
                FROM    employee ei
                WHERE   ei.department = 'sales'
                ORDER BY
                        e.salary
                LIMIT 1
                )
        

        要获取每个部门的值,请使用:

        SELECT  e.*
        FROM    department d
        LEFT JOIN
                employee e
        ON   e.id =
                (
                SELECT  id
                FROM    employee ei
                WHERE   ei.department = d.id
                ORDER BY
                        e.salary
                LIMIT 1
                )
        

        要仅为那些有员工的部门获取值,请使用:

        SELECT  e.*
        FROM    (
                SELECT  DISTINCT eo.department
                FROM    employee eo
                ) d
        JOIN
                employee e
        ON   e.id =
                (
                SELECT  id
                FROM    employee ei
                WHERE   ei.department = d.department
                ORDER BY
                        e.salary
                LIMIT 1
                )
        

        当然,在(department, salary) 上建立索引将大大改善所有三个查询。

        【讨论】:

        • 请注意,OP 还希望查询中包含最小值。这个解决方案很接近,但不是 100% 的要求。
        • 查询选择所有值,包括薪水。
        • 适用于销售最低的员工,那么第一个示例查询,每个部门的最低员工呢?当然,我可以为每个部门运行您的查询,但是任何可以在单个查询中工作的东西?
        • 好点。我没有想到那一排的工资会和最低工资一样。对此感到抱歉。
        【解决方案4】:

        如果您想在每个部门中获得“最便宜”的员工,您将有两个选择:

        SELECT
             E.*     -- Don't actually use *, list out all of your columns
        FROM
             Employees E
        INNER JOIN
             (
                  SELECT
                       department,
                       MIN(salary) AS min_salary
                  FROM
                       Employees
                  GROUP BY
                       department
             ) AS SQ ON
             SQ.department = E.department AND
             SQ.min_salary = E.salary
        

        或者你可以使用:

        SELECT
             E.*
        FROM
             Employees E1
        LEFT OUTER JOIN Employees E2 ON
             E2.department = E1.department AND
             E2.salary < E1.salary
        WHERE
             E2.employee_id IS NULL -- You can use any NOT NULL column here
        

        第二个语句的工作原理是,告诉我所有员工,你在同一部门找不到其他工资较低的员工。

        在这两种情况下,如果两名或多名员工的最低工资相同,您将获得他们(全部)。

        【讨论】:

        • MySQL 有分析功能吗?如果是这样,无论何时您将表连接回自身,您都应该立即想到“使用分析函数更快”
        猜你喜欢
        • 2013-04-06
        • 2012-07-25
        • 2014-09-11
        • 2012-07-25
        • 2013-08-12
        • 2011-08-05
        • 1970-01-01
        • 2018-10-26
        • 2020-07-23
        相关资源
        最近更新 更多