2

mysql 5.5。

我有一个代表工作分配的表格:

   empId   jobNo   workDate   hours
     4      441    10/1/2012    10
     4      441     9/1/2012    22
     4      441     8/1/2012     6

还有一个代表薪水:

   empId   effDate     rate
     4     10/1/2012    6.50
     4      9/1/2012    5.85
     4      6/1/2012    4.00

工资适用于在生效日期或之后完成的所有工作。所以 6 月、7 月和 8 月的汇率是 4.00;sep 是 5.85,oct 是 6.50。

如果我天真地询问十月的工作:

   SELECT Work.empId, Work.jobNo, Work.workDate, Work.hours, Salary.effDate, Salary.rate
   FROM Work
   JOIN Salary ON Work.empId = Salary.empId
   WHERE Work.workDate <= '2012-10-01'
      AND Salary.effDate <= Work.workDate
   ORDER BY Work.jobNo ASC, Work.workDate DESC;

我没有得到我想要的。我得到类似的东西

   4   441   10/1/2012   10   10/1/2012   6.50
   4   441   10/1/2012   10    9/1/2012   5.85
   4   441   10/1/2012   10    6/1/2012   4.00
   4   441    9/1/2012   22    9/1/2012   5.85
   4   441    9/1/2012   22    6/1/2012   4.00
   4   441    8/1/2012    6    6/1/2012   4.00

当我想要

   4   441   10/1/2012   10   10/1/2012   6.50
   4   441    9/1/2012   22    9/1/2012   5.85
   4   441    8/1/2012    6    6/1/2012   4.00

我无法完全理解如何创建我想要的查询。
显然,实际情况有多个员工,多个工作。

谢谢你的帮助。

4

3 回答 3

5

这是您的实际问题:您希望能够根据工作日期 x 工资生效日期,对 Work 中的每条记录检测相应的有效率。当您只是Salary.effDate <= WORK.workDate在工作日期之前获得所有费率时。但你只想要最近的一个。

问题的一个稍微复杂的变体。有很多方法可以做到这一点,这里是一种:

SELECT sel.*, Salary.Rate
FROM
(
     SELECT Work.empId, Work.jobNo, Work.workDate, 
           Work.hours, Max(Salary.effDate) effDate
    FROM WORK
    JOIN Salary ON WORK.empId = Salary.empId
    WHERE WORK.workDate <= '2012-10-01'
       AND Salary.effDate <= WORK.workDate
    GROUP BY WORK.empId, WORK.jobNo, WORK.workDate, WORK.hours
    ORDER BY WORK.jobNo ASC, WORK.workDate DESC
) sel 
INNER JOIN Salary ON sel.empId = Salary.empId 
                  AND sel.EffDate = Salary.EffDate

首先,内部查询检测每个工作记录的最近工资生效日期。然后,我们再次将其与薪水相结合。

请参阅工作SQLFiddle

于 2012-08-15T16:12:51.283 回答
0

您正在使用所谓的 NATURAL JOIN。尝试将单词“JOIN”更改为“LEFT JOIN”,这应该将结果分组在左侧,从而为您提供所需的结果。

于 2012-08-15T15:59:20.553 回答
0

假设工资表有一个由列组成的主键或备用键(唯一索引)empIdeffDate我会做这样的事情:

select w.empID                   as EMPLOYEE_ID   ,
       w.jobNo                   as JOB_NUMBER    ,
       w.workDate                as DATE_WORKED   ,
       w.hours                   as HOURS_WORKED  ,
       rate.HourlyWage           as HOURLY_WAGE   ,
       w.hours * rate.HourlyWage as WAGES_CHARGED ,
       rate.effDateFrom          as HOURLY_WAGE_EFFECTIVE_DATE
from work w
join ( select sfrom.EmpId   as EmpID ,
              sfrom.rate    as HourlyWage ,
              sfrom.EffDate as effDateFrom ,
              ( select min(Effdate) 
                from salary t
                where t.empId   = sfrom.EmpId
                  and t.effDate > sfrom.EffDate
              ) as effDateThru
              from salary sfrom
     ) rate on rate.empID = w.empID
           and rate.EffDateFrom <= w.workDate
           and (    rate.effDateThru is null      -- if rate has not end date, is the current period
                 or rate.effDateThru > w.workDate -- 'date-thru' represents the start date of the next period, so the this upper bound is EXCLUSIVE
               )

我们将工作表与一个虚拟rate表连接起来,该表为我们提供了每个员工的工资和有效的日期范围。每个员工的“当前”行将设置为截止/到期日期null。而且...由于截止/到期日期实际上是下一个工资条目的生效日期,因此上限是排他性的而不是包含性的。因此,范围测试必须测试 null 并且不能使用between.

于 2012-08-15T18:53:33.473 回答