I have the employees table where each employee has a related start_date, end_date and a salary.
NOTE: on the bottom you can find the SQL code to import the structure and data.
+----+-------+------------+------------+---------+
| 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 |
+----+-------+------------+------------+---------+
For a given date range I want to extract the average of the salaries for each month within the given date range.
UPDATE: I would like to have the solution for MySQL 5.6 but it would be great to have also the solution for MySQL 8+ (just for personal knowledge).
If the date range is 2018-08-01 - 2019-01-31, the SQL statement should loop from August 2018 to January 2019 and it has to calculate the average salary for each month:
Following you can see the expected result for the date range 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 |
+------+-------+------------+
NOTE: I solved this problem mixing MySQL with PHP code but for big date range it has to execute too many queries (one each month). So I would like to have a solution using MySQL only.
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');
Once you have all the numbers for each month, add all the numbers together for each month, and then divide them by the total amount of months.
Use AutoSum to quickly find the average Click a cell below the column or to the right of the row of the numbers for which you want to find the average. On the HOME tab, click the arrow next to AutoSum > Average, and then press Enter.
To calculate an average by date in Excel, you can use any of these methods. However, the AVERAGEIF function is probably the easiest way to do it. To use this function, you first need to have your data organized by date in one column. Then, in another column next to it, you can enter the AVERAGEIF function.
Here's a MySQL 8.0 recursive CTE way of doing it. The CTE creates a list of all the year, month
combinations between the minimum start_date
and maximum end_date
in the employees
table, which is then LEFT JOIN
ed to the employees
table to get the average salary for all employees who were working in that particular year and month:
WITH RECURSIVE months (year, month) AS
(
SELECT YEAR(MIN(start_date)) AS year, MONTH(MIN(start_date)) AS month FROM employees
UNION ALL
SELECT year + (month = 12), (month % 12) + 1 FROM months
WHERE STR_TO_DATE(CONCAT_WS('-', year, month, '01'), '%Y-%m-%d') <= (SELECT MAX(end_date) FROM employees)
)
SELECT m.year, m.month, ROUND(AVG(e.salary), 2) AS avg_salary
FROM months m
LEFT JOIN employees e ON STR_TO_DATE(CONCAT_WS('-', m.year, m.month, '01'), '%Y-%m-%d') BETWEEN e.start_date AND e.end_date
WHERE STR_TO_DATE(CONCAT_WS('-', m.year, m.month, '01'), '%Y-%m-%d') BETWEEN '2018-08-01' AND '2019-01-31'
GROUP BY m.year, m.month
Output:
year month avg_salary
2018 8 3333.33
2018 9 3333.33
2018 10 3500.00
2018 11 3500.00
2018 12 3666.67
2019 1 3666.67
Demo on dbfiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With