【问题标题】:How to automaticaly calculate a new field (Column) in MS Access DB 2016 each month如何每月自动计算 MS Access DB 2016 中的新字段(列)
【发布时间】:2020-01-24 14:10:31
【问题描述】:

我在 win10 平台上使用 MS Access 2016。我在 Access tbl_OB_PLAN_ALLT_DISTRIB 中有一个表,其中包含一年中的月份作为标题示例:OCTNOVDEC 等。

我有一个查询,用于计算我所有收到钱的组织的月总价值。

我需要帮助修改查询中的代码以自动将下个月字段添加到该计算中。我目前必须进入查询并每月修改它。

这是我目前使用的:

OB_Plan: Nz([Oct],0)+Nz([NOV],0)+Nz([DEC],0)+Nz([JAN],0)

这在我的查询中作为表达式放置。所以我想要一种在表达式中自动添加下个月的方法。示例:

OB_Plan: Nz([Oct],0)+Nz([NOV],0)+Nz([DEC],0)+Nz([JAN],0)+Nz([FEB],0)

我想我可能需要将其设为函数并在表达式中调用该函数。

任何想法都会有所帮助。 SQL 脚本修改:

SELECT tbl_OB_Plan_ALLT_DISTRIB_Data.Record_ID, ([tbl_OB_Plan_ALLT_DISTRIB_Data]![Directorate] & " " & "(" & [tbl_OB_Plan_ALLT_DISTRIB_Data]![FUND_CENTER] & ")") AS Directorate, tbl_OB_Plan_ALLT_DISTRIB_Data.SAG, tbl_OB_Plan_ALLT_DISTRIB_Data.MDEP, Calc_OB_Plan([JAN],[FEB],[MAR],[APR],[MAY],[JUN],[JUL],[AUG],[SEP],[OCT],[NOV],[DEC]) AS OB_Plan, [001-FINAL_INTEGRATION_TABLE]![AFP-FMEDDW] AS Current_AFP, [001-FINAL_INTEGRATION_TABLE]![ALLT-FMEDDW] AS Allotment_YTD, [001-FINAL_INTEGRATION_TABLE].TITLE
FROM tbl_OB_Plan_ALLT_DISTRIB_Data INNER JOIN [001-FINAL_INTEGRATION_TABLE] ON (tbl_OB_Plan_ALLT_DISTRIB_Data.MDEP = [001-FINAL_INTEGRATION_TABLE].MDEP) AND (tbl_OB_Plan_ALLT_DISTRIB_Data.SAG = [001-FINAL_INTEGRATION_TABLE].SAG)
GROUP BY tbl_OB_Plan_ALLT_DISTRIB_Data.Record_ID, ([tbl_OB_Plan_ALLT_DISTRIB_Data]![Directorate] & " " & "(" & [tbl_OB_Plan_ALLT_DISTRIB_Data]![FUND_CENTER] & ")"), tbl_OB_Plan_ALLT_DISTRIB_Data.SAG, tbl_OB_Plan_ALLT_DISTRIB_Data.MDEP, "", [001-FINAL_INTEGRATION_TABLE]![AFP-FMEDDW], [001-FINAL_INTEGRATION_TABLE]![ALLT-FMEDDW], [001-FINAL_INTEGRATION_TABLE].TITLE;

【问题讨论】:

  • 有什么理由需要两个独立的解决方案? @LeeMac 和 June,可能已经一起工作了(对他们来说更少的努力,对你来说可能更有价值;()。请阅读 How to Ask 并解释每月总和的出现位置。不是每笔交易都存储了价值和日期?

标签: sql vba ms-access


【解决方案1】:

您发现使用标准 MS Access 功能难以实现这一点的主要原因是您的数据库不符合 database normalisation rules

当您发现自己将月份名称硬编码到查询表达式中并因此每个月修改查询结构的那一刻是您的数据库设计应该改变的危险信号。

在您的情况下,根据您提供的信息,我建议在表中定义 Month(最好是整数),或者更好的是在表中定义一个 Date 字段,并显示每个月的数据作为表中的单独记录,而不是单个记录。

进行此更改后,选择变得简单,因为您可以轻松计算您希望在查询的选择条件内选择的月份或日期范围,无需修改查询定义.

如果没有这样的重新设计,解决方案会很丑,例如:

select
    choose
    (
        month(date()),
        Nz([JAN],0),
        Nz([JAN],0)+Nz([FEB],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0)+Nz([AUG],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0)+Nz([AUG],0)+Nz([SEP],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0)+Nz([AUG],0)+Nz([SEP],0)+Nz([OCT],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0)+Nz([AUG],0)+Nz([SEP],0)+Nz([OCT],0)+Nz([NOV],0),
        Nz([JAN],0)+Nz([FEB],0)+Nz([MAR],0)+Nz([APR],0)+Nz([MAY],0)+Nz([JUN],0)+Nz([JUL],0)+Nz([AUG],0)+Nz([SEP],0)+Nz([OCT],0)+Nz([NOV],0)+Nz([DEC],0)
    )
from
    tbl_OB_PLAN_ALLT_DISTRIB

或者:

select sum(t.amount)
from
(
    select 1 as mon, Nz([JAN],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 2 as mon, Nz([FEB],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 3 as mon, Nz([MAR],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 4 as mon, Nz([APR],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 5 as mon, Nz([MAY],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 6 as mon, Nz([JUN],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 7 as mon, Nz([JUL],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 8 as mon, Nz([AUG],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 9 as mon, Nz([SEP],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 10 as mon, Nz([OCT],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 11 as mon, Nz([NOV],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
    union
    select 12 as mon, Nz([DEC],0) as amount
    from tbl_OB_PLAN_ALLT_DISTRIB
) t
where 
    t.mon <= month(date())

或者,作为 VBA 函数:

Function Calc_OB_Plan(vJan, vFeb, vMar, vApr, vMay, vJun, vJul, vAug, vSep, vOct, vNov, vDec) As Double
    Dim Arr()
    Arr = Array(vJan, vFeb, vMar, vApr, vMay, vJun, vJul, vAug, vSep, vOct, vNov, vDec)
    Dim i As Integer
    For i = 0 To Month(Date) - 1
        Calc_OB_Plan = Calc_OB_Plan + Nz(Arr(i), 0)
    Next i
End Function

可以通过以下方式从您的 SQL 查询中调用:

select Calc_OB_Plan([JAN],[FEB],[MAR],[APR],[MAY],[JUN],[JUL],[AUG],[SEP],[OCT],[NOV],[DEC]) as OB_Plan
from tbl_OB_PLAN_ALLT_DISTRIB

编辑:

由于您按所有字段分组,没有任何聚合函数,您可以将group by 子句替换为select distinct 以更有效地获得相同的结果,例如:

SELECT DISTINCT
    tbl_OB_Plan_ALLT_DISTRIB_Data.Record_ID, 
    ([tbl_OB_Plan_ALLT_DISTRIB_Data]![Directorate] & " " & "(" & [tbl_OB_Plan_ALLT_DISTRIB_Data]![FUND_CENTER] & ")") AS Directorate, 
    tbl_OB_Plan_ALLT_DISTRIB_Data.SAG, 
    tbl_OB_Plan_ALLT_DISTRIB_Data.MDEP, 
    Calc_OB_Plan([JAN],[FEB],[MAR],[APR],[MAY],[JUN],[JUL],[AUG],[SEP],[OCT],[NOV],[DEC]) AS OB_Plan, 
    [001-FINAL_INTEGRATION_TABLE]![AFP-FMEDDW] AS Current_AFP, 
    [001-FINAL_INTEGRATION_TABLE]![ALLT-FMEDDW] AS Allotment_YTD, 
    [001-FINAL_INTEGRATION_TABLE].TITLE
FROM 
    tbl_OB_Plan_ALLT_DISTRIB_Data INNER JOIN [001-FINAL_INTEGRATION_TABLE] ON
    tbl_OB_Plan_ALLT_DISTRIB_Data.MDEP = [001-FINAL_INTEGRATION_TABLE].MDEP AND 
    tbl_OB_Plan_ALLT_DISTRIB_Data.SAG = [001-FINAL_INTEGRATION_TABLE].SAG

【讨论】:

  • 确实数据库没有按照正确的规范化规则设计。我只是想让里面的东西起作用。就您提供的第一个选项而言,我是否只需在查询的字段部分中添加它(例如:Expression1:选择选择{在此处粘贴其余代码}并运行我的查询?还是我把它在作为函数的模块中?感谢您的帮助。
  • 由于表达式中的字符数可能会超过设计视图中允许的最大值,因此您需要修改查询的 SQL,用 choose 表达式代替现有的OB_Plan 列的表达式。
  • 我得到一个错误表达式中子查询的语法不正确。 (检查子查询的语法并将子查询括在括号中。)
  • 我现在从调查中看到的错误是您的陈述是正确的字符长度超过了限制,因此将其切断。在我刷新页面之前我没有看到你的帖子。
  • 请勿将代码发布为屏幕截图。我已经展示了如何调用该函数作为我的答案的一部分。请花一些时间研究我的建议并了解代码的工作原理,以回报我为帮助您而投入的时间。
猜你喜欢
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多