我需要总结与有效日期的参考文献相关的数据。
让我们想象一下这些表的工资架构
employee work
+----+------+ +----+--------+------------+
| id | name | | id | emp_id | date |
+----+------+ +----+--------+------------+
| 1 | John | | 1 | 1 | 2012-10-05 |
| 2 | Bob | | 2 | 1 | 2012-02-10 |
+----+------+ | 3 | 2 | 2012-09-03 |
| 4 | 1 | 2012-12-12 |
salary | 5 | 1 | 2012-04-04 |
+----+--------+--------------+------------+ | 6 | 2 | 2012-06-09 |
| id | emp_id | daily_amount | start_date | | 7 | 1 | 2012-07-24 |
+----+--------+--------------+------------+ +----+--------+------------+
| 1 | 1 | 10 | 2012-01-01 |
| 2 | 1 | 15 | 2012-04-16 |
| 3 | 2 | 20 | 2012-05-25 |
+----+--------+--------------+------------+
从2012-01-01 约翰每天支付10天,然后从2012-04-16,他的工资增加到15。 Bob 自2012-05-25以来已支付20美元
现在让我们说我需要计算2012年两名员工的工资。 这是我天真的尝试:
SELECT
emp.name AS "employee"
, SUM(sal.daily_amount) AS "amount"
FROM employee AS emp
JOIN work AS wrk ON (wrk.emp_id = emp.id)
JOIN salary AS sal ON (
sal.emp_id = emp.id
AND wrk.date >= sal.start_date
)
WHERE YEAR(wrk.date) = 2012
GROUP BY emp.id
;
当然它没有给我我想要的东西,因为它没有取得MAX start_date
问题:Bob& S获得的金额是多少?约翰在2012年?
答案 0 :(得分:3)
在SQLfiddle上测试了以下内容:
SELECT employee.name AS "employee",
SUM(s1.daily_amount) AS "amount"
FROM work
INNER JOIN salary s1
ON work.emp_id = s1.emp_id
AND work.date >= s1.start_date
LEFT JOIN salary s2
ON work.emp_id = s2.emp_id
AND work.date >= s2.start_date
AND s2.start_date > s1.start_date
INNER JOIN employee
ON work.emp_id = employee.id
WHERE s2.emp_id IS NULL
GROUP BY work.emp_id
我们的想法是使用s1
和s2
的组合来查找上一个日期:s1
是工作日之前的任何薪资定义,而{{1}只有在没有适用的后期工资定义的情况下才是s2
。
答案 1 :(得分:2)
嗯,你有salary table
的开始日期,但你也需要一个结束日期。
您可以使用派生表执行此操作:
SELECT
s_1.emp_id,
s_1.daily_amount,
s_1.start_date AS start,
DATE_ADD(MIN(s_2.start_date), INTERVAL -1 DAY) AS end
FROM
salary s_1
LEFT JOIN salary s_2
ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
GROUP BY s_1.emp_id, s_1.start_date
最后看起来像:
SELECT
employee.name,
SUM(s.daily_amount) AS amount
FROM
employee
JOIN work
ON employee.id = work.emp_id
JOIN
(
SELECT
s_1.emp_id,
s_1.daily_amount,
s_1.start_date AS start,
DATE_ADD(MIN(s_2.start_date), INTERVAL -1 DAY) AS end
FROM
salary s_1
LEFT JOIN salary s_2
ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
GROUP BY s_1.emp_id, s_1.start_date
) AS s
ON employee.id = s.emp_id
AND
work.date >= s.start
AND
(work.date <= s.end OR s.end IS NULL)
GROUP BY employee.id
修改强>
没有DATE_ADD()
SELECT
employee.name,
SUM(s.daily_amount) AS amount
FROM
employee
JOIN work
ON employee.id = work.emp_id
JOIN
(
SELECT
s_1.emp_id,
s_1.daily_amount,
s_1.start_date AS start,
MIN(s_2.start_date) AS end
FROM
salary s_1
LEFT JOIN salary s_2
ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
GROUP BY s_1.emp_id, s_1.start_date
) AS s
ON employee.id = s.emp_id
AND
work.date >= s.start
AND
(work.date < s.end OR s.end IS NULL)
GROUP BY employee.id