【问题标题】:employee database with varing salary over time工资随时间变化的员工数据库
【发布时间】:2011-01-16 20:44:15
【问题描述】:

我有以下表格:

PROJECTS - project_id, name
EMPLOYEES - employee_id, name
SALARY - employee_id, date, per_hour
HOURS - log_id, project_id, employee_id, date, num_hours

我需要查询一个项目的成本。问题是薪水可能会有所不同。例如,一个人可以得到加薪。

SALARY 表记录员工的每小时费用。成本的每一次变化都会记录其日期。

如何查询此信息以确保 HOURS 表中的日志始终与 SALARY 表中的正确条目匹配。正确的匹配是.. 根据小时日志的日期,从工资表中获取日志日期之前日期最高的行。

ie.. 如果工作是在 2 月 14 日进行的。从 Salary 表中获取该员工的行,日期最高.. 但仍然在 14 号之前。

谢谢,

【问题讨论】:

    标签: sql join schema


    【解决方案1】:

    您需要的是 SALARY 的结束日期。将新记录插入到员工的 SALARY 中时,具有最高日期的先前记录(或者更好的是,根据 cletus 的建议将当前标志设置为“Y”)应将其结束日期列设置为与新记录的开始日期。

    这应该适用于您当前的架构,但请注意它可能会很慢。

    SELECT
      SUM(h.num_hours * s.per_hour) AS cost
    FROM PROJECTS p
    INNER JOIN HOURS h
      ON p.project_id = h.project_id
    INNER JOIN (
        SELECT
          s1.employee_id,
          s1.date AS start_date,
          MIN(s2.date) AS end_date
        FROM SALARY s1
        INNER JOIN SALARY s2
          ON s1.employee_id = s2.employee_id
          AND s1.date < s2.date
        GROUP BY
          s1.employee_id,
          s1.date) s
      ON h.employee_id = s.employee_id
      AND h.date >= s.start_date
      AND h.date < s.end_date
    

    【讨论】:

      【解决方案2】:

      在“小时”表中实际记录您使用的工资值(不要根据 ID 链接它)。这将在未来为您提供更大的灵活性。

      【讨论】:

        【解决方案3】:

        我发现像这样处理跨越日期的查询的最简单方法是存储StartDateEndDate,其中EndDateNULL 的当前工资。我使用触发器确保EndDate 只有一个NULL 值,并且没有重叠的日期范围或范围之间的间隙。 StartDate 不能为空,因为它永远不是有效值。

        那么你的加入就很简单了:

        select h.num_hours, s.per_hour
        from hours h
        inner join salary s on h.employee_id = s.employee_id 
            and h.date >= s.StartDate and (h.date <= s.EndDate or s.EndDate is null)
        

        【讨论】:

        • @cletus 这是一个工资系统,这意味着它计算支付给人们的金额。这是他们赖以生存的钱。我怀疑正确性是相当重要的,任何在工资单上有可扩展性问题的公司都能够负担得起正确处理工资单的硬件。这是一个游戏或 Facebook 或类似的东西,当然,权衡会有所不同。
        • @cletus:“过早的优化是万恶之源”是另一个口头禅;您将问题重铸为与绩效有关,而不是为问题提供解决方案,即如何查询历史工资。
        • @cletus:令人失望的是,您选择删除您的答案和 cmets(以及其他用户在您的答案中的 cmets)以及您在我的答案中的 cmets,而不是站在您的话后面或承认您的解决方案存在一些缺陷。健康的辩论是 SO(和学习过程)的重要组成部分,无论 SO 社区最终偏爱哪种观点,讨论都是有价值的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-05
        • 2017-09-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-15
        • 2023-04-03
        • 1970-01-01
        相关资源
        最近更新 更多