SQL FIDDLE HERE:http://sqlfiddle.com/#!2/6c7f7/5 **
我正在建立一个工资单数据库,直到现在一切都很完美。我从一开始就没有提到的一个重要概念是,当员工的薪资等级发生变化时,是否会从薪资等级变更之日起反映出来?以前,查询只会按照员工姓名旁边的薪水等级进行查询,但如果他的费率在一周中的每一天都发生变化(例如),那么这是不准确的吗?
在其他人的帮助下,我已经达到了上面的SQL小提琴,但结果并没有反映出正确的答案。目前,该小提琴中的“where”子句使用了historyemployeepay表中不正确的工资率。它应该选择'null'ToDate行并使用它作为基本速率?有人能告诉我出了什么问题吗?
答案 0 :(得分:1)
正如Jacob提供了一个选项,我也会对规范化做一些改变。
Table PayCodes
PayCodeID PayCodeDescription timesBase timesOtherRate timesMealRate
1 01 Ordinary 1.0 0.0 0.0
2 02 Overtime 1.5 0.0 0.0
3 03 Overtime 2.0 0.0 0.0
4 78 Crib .333 0.0 0.0
5 CZ Meal Allowance PS 0.0 0.0 1.0
6 86Y Sick with Cert 1.0 0.0 0.0
etc...
然后,在您的每小时表中,数据输入将由数据驱动以获取相应的付费代码,保存内部ID代码与硬代码字引用。如果您不想显示任何神秘的引用,您甚至可以为“PayStubCaption”构建另一列。
对于您的员工工资率历史记录,字段包括开始/结束日期,因为这是一个罕见的场合(一年一次??可能两次?)同时包含给定费率的开始和结束日期,并且包括(在这个例子是你跟踪的3个比率..
PayHistoryID EmployeeID FromDate ToDate BaseRate OtherRate MealRate
1 84238 2012-10-10 2013-9-30 10.0 15.0 3.5
2 84238 2013-10-1 (current) 14.0 21.0 6
...
这些可以极大地帮助简化查询下游......
至于添加到要应用的每个速率的查询,如果你不允许坏数据,这将成为一个简单的连接,例如一个记录上的from / to范围与同一个人的另一个记录的另一个。
select
...
sum( case/when... PRT.BaseRate ) as ...
from
other join tables...
JOIN PayRatesTable PRT
on employeehours_copy.EmployeeID PRT.EmployeeID
AND PRT.FromDate <= employeehours_copy.Worked
AND ( PRT.ToDate IS NULL OR employeehours_copy.Worked <= PRT.ToDate )
关于简化阅读的注意事项,我已将样本“PayRateTable”别名化为PRT。然后就是 使用“PRT.BaseRate”或其他费率,每次计算的费率,而不是员工表中可能的费率。您还应养成为所有table.column(或alias.column)限定歧义问题的习惯,特别是在每个表中列名相同的连接时。(/ p>
答案 1 :(得分:0)
我的建议是模块化一点。如果这是我的项目,我会创建一个处理每个时间段的过程。
让我们说鲍勃在1月1日上午8点到下午5点,1月2日上午11点到下午6点钟表。 1月1日,鲍勃赚了10小时,而在2日,他赚了20美元。
我们的数据可能看起来像
Payrange
--------
Dec 20 2012 - Jan 01 2013 | $10
Jac 02 2013 - Jan 30 2013 | $20
Clock
-----
Jan 01 2013 | 9 hours
Jan 02 2013 | 7 hours
使用此信息,您可以将之后的每一行时间加总将其与相应的支付范围相乘。