ejemplos avg sql mysql aggregate-functions

avg - sql max group by



Campos adicionales con SQL MIN() y GROUP BY (4)

Al usar la función SQL MIN (), junto con GROUP BY, ¿alguna columna adicional (no la columna MIN o una de las columnas GROUP BY) coincidirá con los datos en la fila MIN correspondiente?

Por ejemplo, dada una tabla con los nombres de los departamentos, los nombres de los empleados y el salario:

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

Obviamente obtendré dos buenas columnas, el salario mínimo y el departamento. ¿El nombre del empleado (y cualquier otro campo del empleado) será de la misma fila? Es decir, la fila con el MIN (salario)?

Sé que es muy posible que haya dos empleados con el mismo salario (y el más bajo), pero todo lo que me preocupa (ahora) es obtener toda la información sobre el (o un ) empleado más barato.

¿Esto seleccionaría al vendedor más barato?

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

Básicamente, ¿puedo estar seguro de que los datos devueltos junto con la función MIN () coincidirán con el registro (o un solo ) con ese valor mínimo?

Si la base de datos es importante, estoy trabajando con MySql.


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. Aquí está la consulta usando funciones analíticas y ROW_NUM

seleccione first_name, salario de (seleccione first_name, salario, Row_NUMBER () sobre (PARTITION BY DEPARTMENT_ID ORDER BYlarner ASC) como row_count de empleados) donde row_count = 1;


Si quisiera tener al empleado "más barato" en cada departamento, tendría dos opciones por encima 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 puedes 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 afirmación funciona al decir efectivamente: muéstreme a todos los empleados donde no puede encontrar a otro empleado en el mismo departamento con un salario más bajo.

En ambos casos, si dos o más empleados tienen salarios iguales que son el mínimo, usted obtendrá ambos (todos).


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 valores para cada departamento, use:

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 valores solo para aquellos departamentos que tienen empleados, use:

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á enormemente las tres consultas.