Dan*_*Dan 8 mysql sql group-by date aggregate-functions
我有employees表,其中每个员工都有一个相关的start_date,end_date和一个工资.
注意:在底部,您可以找到导入结构和数据的SQL代码.
+----+-------+------------+------------+---------+
| id | name | start_date | end_date | salary |
+----+-------+------------+------------+---------+
| 1 | Mark | 2017-05-01 | 2020-01-31 | 2000.00 |
| 2 | Tania | 2018-02-01 | 2019-08-31 | 5000.00 |
| 3 | Leo | 2018-02-01 | 2018-09-30 | 3000.00 |
| 4 | Elsa | 2018-12-01 | 2020-05-31 | 4000.00 |
+----+-------+------------+------------+---------+
Run Code Online (Sandbox Code Playgroud)
对于给定的日期范围,我想提取给定日期范围内每个月的工资平均值.
更新:我想拥有MySQL 5.6的解决方案,但是拥有MySQL 8+的解决方案(仅用于个人知识)会很棒.
如果日期范围是2018-08-01 - 2019-01-31,则SQL语句应从2018年8月到2019年1月循环,并且必须计算每个月的平均工资:
您可以看到日期范围2018-08-01 - 2019-01-31的预期结果
+------+-------+------------+
| year | month | avg_salary |
+------+-------+------------+
| 2018 | 08 | 3333.33 |
| 2018 | 09 | 3333.33 |
| 2018 | 10 | 3500.00 |
| 2018 | 11 | 3500.00 |
| 2018 | 12 | 3666.67 |
| 2019 | 01 | 3666.67 |
+------+-------+------------+
Run Code Online (Sandbox Code Playgroud)
注意:我解决了将MySQL与PHP代码混合的问题,但对于大日期范围,它必须执行太多查询(每月一个).所以我想只使用MySQL的解决方案.
CREATE TABLE `employees` (
`id` int(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`salary` decimal(10,2) DEFAULT NULL
);
INSERT INTO `employees` (`id`, `name`, `start_date`, `end_date`, `salary`) VALUES
(1, 'Mark', '2017-05-01', '2020-01-31', '2000.00'),
(2, 'Tania', '2018-02-01', '2019-08-31', '5000.00'),
(3, 'Leo', '2018-02-01', '2018-09-30', '3000.00'),
(4, 'Elsa', '2018-12-01', '2020-05-31', '4000.00');
Run Code Online (Sandbox Code Playgroud)
您可以简单地输入所需的月份(或使用 PHP 代码生成它们)并加入它:
SELECT ym, AVG(salary)
FROM (
SELECT '2018-08-01' + INTERVAL 0 MONTH AS ym UNION ALL
SELECT '2018-08-01' + INTERVAL 1 MONTH UNION ALL
SELECT '2018-08-01' + INTERVAL 2 MONTH UNION ALL
SELECT '2018-08-01' + INTERVAL 3 MONTH UNION ALL
SELECT '2018-08-01' + INTERVAL 4 MONTH UNION ALL
SELECT '2018-08-01' + INTERVAL 5 MONTH
) AS yearmonths
JOIN employees ON ym BETWEEN start_date AND end_date
GROUP BY ym
Run Code Online (Sandbox Code Playgroud)
如果您有一个包含数字 0、1、... 的表,那么您可以使用它。您甚至可以使用任何具有足够行数的表:
SELECT ym, AVG(salary)
FROM (
SELECT '2018-08-01' + INTERVAL @n := @n + 1 MONTH AS ym
FROM anytable, (SELECT @n := -1) x
LIMIT 100
) AS yearmonths
JOIN employees ON ym BETWEEN start_date AND end_date
WHERE ym <= '2019-01-01'
GROUP BY ym
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
128 次 |
| 最近记录: |