SQL 在 MS Access 中(在辅助 table 中总结数据,基于它在两个日期之间 + 记录中的匹配名称)

SQL in MS Access (sum data in a secondary table based on it being between two dates + matching names in records)

我有两个 table:

工资单:

Payslip ID Salary Deduction Payslip Date Employee Name
1 calc 5/29/2022 ABC
2 calc 4/29/2022 ABC
3 calc 3/29/2022 ABC
4 calc 2/28/2022 ABC

工资扣除:

Deduction ID Deduction Date Deduction Amount Employee Name
1 3/30/2022 50 ABC
2 5/10/2022 100 ABC
3 5/15/2022 100 ABC

我有两个 tables “工资单”和“工资扣除额”。”扣除额已从总工资单金额中删除(此处未显示,因为不需要解决问题)。

我正在尝试计算每个工资周期的应计扣除总额。 (4/29/2022 -> 5/29/2022 为一个薪资周期)。在上面的示例中,两个日期(即工资周期)之间的总扣除额应为 200。我希望在工资单 table 中的工资单 ID=1 的工资扣除字段中显示该数字.

以同样的方式,2022 年 3 月 30 日的扣款应该显示在薪水单 table 中薪水单 ID =2 的记录中......等等。工资单 id = 3 中的扣除金额应为零,因为在 2/28-3/29 期间没有扣除。

这应该在两个 table 中员工姓名相同的情况下完成,因此“ABC 在 2/28/2022 和 3/29/ 之间的周期中从工资中扣除了 50/ 2022"等

所有这些都应该以一种形式递归更新。因此,控件应该能够查询 tables 的数据并将其解析到表单中的相应字段(并通过关联,table)。

考虑 DSum domain aggregate which is available as an expression function, VBA function, and SQL function in MS Access (frontend GUI but not backend connection). Similarly, you can use DLookUp (which I advised on your previous question) 在表达式参数中调用 SUM()

具体来说,将其他 table 中的 Salary Deduction 列与对应的 Employee Name 相加,其中 Deduction Date 属于 PaySlip Date 且小于一的日期范围使用后一个月 DateAdd.

表达式 (在[Salary PaySlip]窗体的窗体设计中设置[Salary Deduction]文本框的控制源)

=DSum("[Deduction Amount]", 
      "[Salary Deductions]", 
      "[Employee Name] = '" & [Employee Name] & "' AND
       [Deduction Date] >= #" & [PaySlip Date] & "#
                    AND <  #" & DateAdd("m", 1, [PaySlip Date]) & "#") 

VBA (以编程方式计算控制源)

Forms![Salary PaySlip]![Salary Deduction] = DSum( _
    "[Deduction Amount]", _
    "[Salary Deductions]", _
    "[Employee Name] = '" & Forms![Salary PaySlip]![Employee Name] & "' AND " _ 
     & "[Deduction Date] >= #" & Forms![Salary PaySlip]![PaySlip Date] & "#" _
     & "             AND <  #" & DateAdd("m", 1, Forms![Salary PaySlip]![PaySlip Date]) & "#" _
)

SQL

UPDATE (使用DSum保存数据到table——不能使用subquery

UPDATE [Salary PaySlip] p
SET p.[Salary Deduction] = DSum(
    "[Deduction Amount]", 
    "[Salary Deductions]", 
    "[Employee Name] = '" & p.[Employee Name] & "' AND
     [Deduction Date] >= #" & p.[PaySlip Date] & "#
                  AND <  #" & DateAdd("m", 1, p.[PaySlip Date]) & "#"
) 

或者,您可以使用相关的聚合子查询,这对于足够大的数据可能会产生性能问题。希望很快有一天 MS Access 团队将 add support for window functions(根据 SQL ANSI 2003)到 Access SQL 方言!

SELECT (使用相关聚合子查询)

SELECT p.[PaySlip ID],
       (SELECT SUM([Deduction Amount])
        FROM [Salary Deductions] d
        WHERE d.[Employee Name] = p.[Employee Name]
          AND d.[Deduction Date] >= p.[PaySlip Date]
                             AND <  DateAdd('m', 1, p.[PaySlip Date])
       ) AS [Salary Deduction],
       p.[PaySlip Date]
       p.[Employee Name]
FROM [Salary Payslips] p