Дополнительные поля с помощью SQL MIN () и GROUP BY - PullRequest
23 голосов
/ 07 апреля 2009

При использовании функции SQL MIN () вместе с GROUP BY будут ли какие-либо дополнительные столбцы (не столбец MIN или один из столбцов GROUP BY) соответствовать данным в соответствующей строке MIN?

Например, для таблицы с названиями отделов, именами сотрудников и зарплатой:

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

Очевидно, я получу две хорошие колонки, минимальную зарплату и отдел. Имя сотрудника (и любые другие поля сотрудника) будут из той же строки? А именно строка с МИН (зарплатой)?

Я знаю, что вполне может быть два сотрудника с одинаковой (и самой низкой) зарплатой, но все, что меня беспокоит (сейчас), это получение всей информации о (или единственном ) самом дешевом работник.

Будет ли выбран самый дешевый продавец?

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

По сути, могу ли я быть уверен, что данные, возвращаемые вместе с функцией MIN (), будут соответствовать (или одиночная ) запись с этим минимальным значением?

Если база данных имеет значение, я работаю с MySql.

Ответы [ 4 ]

22 голосов
/ 07 апреля 2009

Если вы хотите получить «самого дешевого» сотрудника в каждом отделе, у вас будет два варианта:

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

Второе утверждение работает, фактически говоря, покажите всем сотрудникам, где вы не можете найти другого сотрудника в том же отделе с более низкой зарплатой.

В обоих случаях, если у двух или более работников одинаковая минимальная заработная плата, вы получите их обоих (всех).

1 голос
/ 07 апреля 2009
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) значительно улучшит все три запроса.

0 голосов
/ 21 февраля 2017

Другим подходом может быть использование аналитических функций. Вот запрос с использованием аналитических функций и функций ROW_NUM

выберите first_name, оклад из (выберите first_name, оклад, Row_NUMBER () более (PARTITION BY DEPARTMENT_ID ORDER BY оклад ASC) в качестве row_count от сотрудников), где row_count = 1;

0 голосов
/ 17 июля 2012

Самое быстрое решение:

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