SQL - 如何获取每个部门的员工平均工资?
SQL - How can I get the average employee salary for each department?
这是表的 UML:https://dev.mysql.com/doc/employee/en/sakila-structure.html
这是我的尝试:
SELECT
CONCAT(employees.first_name, ' ', employees.last_name) AS 'EmployeeName',
salaries.emp_no AS 'Employee Number',
departments.dept_no AS 'Department Number',
departments.dept_name AS 'Department name',
AVG(salaries.salary) AS 'Average salary'
FROM salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN employees
ON salaries.emp_no = employees.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
GROUP BY salaries.emp_no,
dept_emp.dept_no
我只是得到一个人工作过的所有部门的平均员工工资。
我想要的结果必须按每个部门的每个员工分组。感谢任何帮助。
你可以试试这个查询
SELECT
CONCAT(employees.first_name, ' ', employees.last_name) AS 'EmployeeName',
salaries.emp_no AS 'Employee Number',
departments.dept_no AS 'Department Number',
departments.dept_name AS 'Department name',
Cte_DepartmentSalaries.AvgSalary AS 'Average Salary'
--AVG(salaries.salary) AS 'Average salary'
FROM salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN employees
ON salaries.emp_no = employees.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
LEFT JOIN (SELECT
departments.dept_no,
departments.dept_name,
AVG(Salaries.Salary) AS AvgSalary
FROM Salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
GROUP BY departments.dept_no,
departments.dept_name) AS Cte_DepartmentSalaries
ON dept_emp.dept_no = Cte_DepartmentSalaries.dept_no
将您的群组更改为
GROUP BY employees.first_name, employees.last_name,
salaries.emp_no, departments.dept_no, departments.dept_name
mysql 允许您(恕我直言,以一种无用的方式)不将所有列用于分组依据。与其他平台不同,如果它们不在聚合函数中,则强制您将它们全部放入。所以你得到了不止一个同一行,但你无法分辨,因为 mysql 为你压扁了它们。
您可能在加入时也需要这个
INNER JOIN dept_emp ON salaries.emp_no = dept_emp.emp_no
AND salaries.from_date = dept_emp.from_date
AND salaries.to_date = dept_emp.to_date
如果您加入 to_date 从日期到现在之间的薪水,您将获得这些时间段内薪水的任何变化。
SELECT CONCAT(e.first_name,' ',e.last_name) AS 'EmployeeName',
s.emp_no AS 'Employee Number',
d.dept_no AS 'Department Number',
d.dept_name AS 'Department name',
AVG(s.salaries.salary) AS 'Average salary'
FROM employees e
JOIN dept_emp de ON e.emp_no = de.emp_no
JOIN salaries s ON s.emp_no = de.emp_no
AND (de.to_date >= s.from_date AND de.to_date <= s.to_date)
JOIN departments d ON d.dept_no = de.dept_no
GROUP BY s.emp_no,
d.dept_no
看起来您需要检查员工工资历史记录 (salaries
table) 和员工部门的 from_date
和 to_date
是否存在重叠历史 (dept_emp
table).
假设 NULL 的 to_date
值表示 "current",要找到重叠,连接将是这样的:
FROM salaries s
JOIN dept_emp de
ON ( de.emp_no = s.emp_no )
AND ( de.from_date <= s.to_date OR s.to_date IS NULL )
AND ( de.to_date >= s.from_date OR de.to_date IS NULL )
就获得平均工资而言,这会稍微复杂一些,具体取决于您如何定义 "average"。
举个例子,某部门员工,一年年工资2万,然后四年[=35年工资3万=] 年...平均工资应该报告为 25,000(两个不同值的平均值),还是 28,000(所有年份的总工资除以年数。)
为了得到后一个结果,我们可以使用一个表达式来计算工资在部门中有效的天数...
TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
我们可以将其乘以有效工资,将所有这些加在一起,然后除以总天数:
SUM(days*salary)/SUM(days)
类似这样的表达式:
SUM( TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
*
s.salary
)
/
SUM( TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
)
要仅查找 table 的平均工资,请使用此 mySQL 查询。
SELECT AVG(salary), COUNT(*)
FROM employees;MY
SELECT AVG(工资)来自员工
分组依据(departments_id);
这是表的 UML:https://dev.mysql.com/doc/employee/en/sakila-structure.html
这是我的尝试:
SELECT
CONCAT(employees.first_name, ' ', employees.last_name) AS 'EmployeeName',
salaries.emp_no AS 'Employee Number',
departments.dept_no AS 'Department Number',
departments.dept_name AS 'Department name',
AVG(salaries.salary) AS 'Average salary'
FROM salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN employees
ON salaries.emp_no = employees.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
GROUP BY salaries.emp_no,
dept_emp.dept_no
我只是得到一个人工作过的所有部门的平均员工工资。 我想要的结果必须按每个部门的每个员工分组。感谢任何帮助。
你可以试试这个查询
SELECT
CONCAT(employees.first_name, ' ', employees.last_name) AS 'EmployeeName',
salaries.emp_no AS 'Employee Number',
departments.dept_no AS 'Department Number',
departments.dept_name AS 'Department name',
Cte_DepartmentSalaries.AvgSalary AS 'Average Salary'
--AVG(salaries.salary) AS 'Average salary'
FROM salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN employees
ON salaries.emp_no = employees.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
LEFT JOIN (SELECT
departments.dept_no,
departments.dept_name,
AVG(Salaries.Salary) AS AvgSalary
FROM Salaries
INNER JOIN dept_emp
ON salaries.emp_no = dept_emp.emp_no
INNER JOIN departments
ON dept_emp.dept_no = departments.dept_no
GROUP BY departments.dept_no,
departments.dept_name) AS Cte_DepartmentSalaries
ON dept_emp.dept_no = Cte_DepartmentSalaries.dept_no
将您的群组更改为
GROUP BY employees.first_name, employees.last_name,
salaries.emp_no, departments.dept_no, departments.dept_name
mysql 允许您(恕我直言,以一种无用的方式)不将所有列用于分组依据。与其他平台不同,如果它们不在聚合函数中,则强制您将它们全部放入。所以你得到了不止一个同一行,但你无法分辨,因为 mysql 为你压扁了它们。
您可能在加入时也需要这个
INNER JOIN dept_emp ON salaries.emp_no = dept_emp.emp_no
AND salaries.from_date = dept_emp.from_date
AND salaries.to_date = dept_emp.to_date
如果您加入 to_date 从日期到现在之间的薪水,您将获得这些时间段内薪水的任何变化。
SELECT CONCAT(e.first_name,' ',e.last_name) AS 'EmployeeName',
s.emp_no AS 'Employee Number',
d.dept_no AS 'Department Number',
d.dept_name AS 'Department name',
AVG(s.salaries.salary) AS 'Average salary'
FROM employees e
JOIN dept_emp de ON e.emp_no = de.emp_no
JOIN salaries s ON s.emp_no = de.emp_no
AND (de.to_date >= s.from_date AND de.to_date <= s.to_date)
JOIN departments d ON d.dept_no = de.dept_no
GROUP BY s.emp_no,
d.dept_no
看起来您需要检查员工工资历史记录 (salaries
table) 和员工部门的 from_date
和 to_date
是否存在重叠历史 (dept_emp
table).
假设 NULL 的 to_date
值表示 "current",要找到重叠,连接将是这样的:
FROM salaries s
JOIN dept_emp de
ON ( de.emp_no = s.emp_no )
AND ( de.from_date <= s.to_date OR s.to_date IS NULL )
AND ( de.to_date >= s.from_date OR de.to_date IS NULL )
就获得平均工资而言,这会稍微复杂一些,具体取决于您如何定义 "average"。
举个例子,某部门员工,一年年工资2万,然后四年[=35年工资3万=] 年...平均工资应该报告为 25,000(两个不同值的平均值),还是 28,000(所有年份的总工资除以年数。)
为了得到后一个结果,我们可以使用一个表达式来计算工资在部门中有效的天数...
TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
我们可以将其乘以有效工资,将所有这些加在一起,然后除以总天数:
SUM(days*salary)/SUM(days)
类似这样的表达式:
SUM( TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
*
s.salary
)
/
SUM( TIMESTAMPDIFF(DAY
,GREATEST(de.from_date,s.from_date)
,LEAST(IFNULL(de.to_date,DATE(NOW())),IFNULL(s.to_date,DATE(NOW())))
)
)
要仅查找 table 的平均工资,请使用此 mySQL 查询。
SELECT AVG(salary), COUNT(*)
FROM employees;MY
SELECT AVG(工资)来自员工 分组依据(departments_id);