Los campos adicionales con SQL MIN () y GROUP BY
-
05-09-2019 - |
Pregunta
Al utilizar la función SQL MIN (), junto con GROUP BY, habrá ningún columnas adicionales (no la columna de la MIN, o uno de los GROUP BY columnas) que coincida con los datos en la fila MIN juego?
Por ejemplo, dada una tabla con los nombres de departamento, los nombres de los empleados, y el salario:
SELECT MIN(e.salary), e.* FROM employee e GROUP BY department
Obviamente voy a conseguir dos buenas columnas, el salario mínimo y el departamento. ¿El nombre del empleado (y cualquier otro campo de empleados) ser de la misma fila? A saber, la fila con el MIN (sueldo)?
Sé que muy posiblemente podría haber dos empleados con el mismo (y más bajo) sueldo, pero lo único que me preocupa (ahora) es conseguir toda la información sobre la (o un solo ) más barata empleado.
¿Esto selecciona el vendedor más barato?
SELECT min(salary), e.* FROM employee e WHERE department = 'sales'
En esencia, puedo estar seguro de que los datos devueltos junto con la función MIN () se corresponde con el registro (o un solo ) con el valor mínimo?
Si los asuntos de bases de datos, estoy trabajando con MySQL.
Solución
Si usted quiere conseguir que el empleado "más barata" en cada departamento que tendría dos opciones de la parte superior de mi cabeza:
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
O puede usar:
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
La segunda declaración diciendo funciona efectivamente, me muestran todos los empleados donde no se puede encontrar otro empleado en el mismo departamento con un sueldo inferior.
En ambos casos, si dos o más trabajadores tienen los mismos salarios que son el mínimo que recibirá a los dos (todos).
Otros consejos
SELECT e.*
FROM employee e
WHERE e.id =
(
SELECT id
FROM employee ei
WHERE ei.department = 'sales'
ORDER BY
e.salary
LIMIT 1
)
Para obtener los valores para cada departamento, utilice:
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
)
Para obtener los valores sólo para aquellos departamentos que tienen los empleados, uso:
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
)
Por supuesto, tener un índice en (department, salary)
mejorará en gran medida las tres consultas.
La solución más rápida:
SET @dep := '';
SELECT * FROM (
SELECT * FROM `employee` ORDER BY `department`, `salary`
) AS t WHERE IF ( @dep = t.`department`, FALSE, ( @dep := t.`department` ) OR TRUE );
Otro enfoque puede ser el uso de funciones analíticas. Ésta es la consulta utilizando las funciones de análisis y ROW_NUM
selecciona FIRST_NAME, sueldo a partir de (seleccione FIRST_NAME, salario, ROW_NUMBER () sobre (partición POR DEPARTMENT_ID ORDER BY ASC salario) como row_count de empleados) donde row_count = 1;