SQL将值与特定年份的平均值进行比较
Posted
技术标签:
【中文标题】SQL将值与特定年份的平均值进行比较【英文标题】:SQL comparing value to average value for a specific year 【发布时间】:2018-10-03 18:18:30 【问题描述】:期望的输出:我想选择 1991 年工资高于 1991 年平均水平的所有员工的头衔。
当前代码:
USE employees;
SELECT t.title
FROM employees emps INNER JOIN
employees.salaries s
ON s.emp_no = emps.emp_no INNER JOIN
employees.titles t
ON t.emp_no = s.emp_no
WHERE s.from_date LIKE '1991%' AND s.salary >
员工表:
CREATE TABLE employees (
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender ENUM ('M','F') NOT NULL,
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
工资表:
CREATE TABLE salaries (
emp_no INT NOT NULL,
salary INT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, from_date)
标题表:
CREATE TABLE titles (
emp_no INT NOT NULL,
title VARCHAR(50) NOT NULL,
from_date DATE NOT NULL,
to_date DATE,
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no,title, from_date)
必须使用薪金表中的from_date。
【问题讨论】:
使用YEAR()
函数从日期获取年份值。
样本数据和期望的结果总是可取的
而这一点...select avg(s.salary)
.. 显然缺少什么,对吧?
清理了我的代码,它正在从 from_date 为 1990 的员工中选择头衔,但我不知道如何在 where 条件下获得高于平均工资
【参考方案1】:
首先,工资表中有时间范围。一个人可以为一份薪水工作整个 1991 年。例如,对于从 1989 年到 2000 年以相同工资工作的人来说就是这种情况。但是一个人也可以在一年中的一部分时间为一份薪水工作,另一部分为另一份薪水工作(例如,七月份的加薪)。一个人可能在 1991 年 12 月 1 日开始。或者在 1991 年 1 月 15 日退出。你想如何计算平均值?
假设您只计算 1991 年的所有工资记录。例如A人1月份工作1000,其余时间3000,B人全年工作1000,C人只在6月份工作2000,7月份工作4000。计算:(1000 + 3000 + 1000 + 3300 + 3700) / 5 = 2400。1991年工资高于2400的人是A和C。
select *
from titles
where emp_no in
(
select emp_no
from salaries
where from_date <= date '1991-12-31' and to_date >= date '1991-01-01'
and salary >
(
select avg(salary)
from salaries
where from_date <= date '1991-12-31' and to_date >= date '1991-01-01'
)
);
您可能还想将标题限制为 1991 年。我不知道。也许您甚至希望他们匹配工资高于平均水平的时间跨度。在这种情况下,您必须寻找重叠的时间范围。 (例1:6月加薪,7月新职称高薪2职。例2:6月新职,7月加薪1职高薪。)
如果您有 mysql 8.0,则可以使用 WITH
子句选择 1991 年的薪水,以使查询更具可读性。
【讨论】:
【参考方案2】: 在 Derived Table 中,计算 1991 年的平均工资。您可以使用 Year() 函数来确定给定 MySQL 日期的年份。 Cross Join 与派生表,这样每一行都有一个avg_salary_in_1991
字段,允许比较。
在where
中添加一个条件,以便员工salary
应该大于计算出的avg_salary_in_1991
。
尝试以下方法:
USE employees;
SELECT t.title
FROM employees AS emps
INNER JOIN employees.salaries AS s ON s.emp_no = emps.emp_no
INNER JOIN employees.titles AS t ON t.emp_no = s.emp_no
CROSS JOIN (SELECT AVG(s2.salary) AS avg_salary_in_1991
employees.salaries AS s2
WHERE YEAR(s2.from_date) = 1991) AS avg_sal_1991
WHERE YEAR(s.from_date) = 1991 AND
s.salary > avg_sal_1991.avg_salary_in_1991
【讨论】:
这不会想念1991年没有加薪的每个人吗?如果我在 1990-1992 年每小时赚 15 美元,那我就不会出现了,对吧?只是指出派生表应该说任何跨越 1991 年的工资记录,而不是任何包括 1991 年的工资记录。 @MJB 同意,但我正在根据 OP 的话制定查询:“必须使用薪金表中的 from_date。” 我明白了。我的解释是,使用它来确保薪水跨越该范围是如何做到的。 OP 可以决定哪个是正确的,但我现在明白你的意思了。以上是关于SQL将值与特定年份的平均值进行比较的主要内容,如果未能解决你的问题,请参考以下文章
将一个表中的值与另一表中具有相同属性的值的平均值计算进行比较
pandas使用resample函数计算每个月的统计均值使用matplotlib可视化特定年份的按月均值
pandas使用pct_change函数计算月均值环比变化率使用matplotlib可视化特定年份的按月均值变化率(pct_change compute change rate)