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_dateto_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);