【问题标题】:MS Access query incorrectly summing totalsMS Access 查询错误地汇总总数
【发布时间】:2016-02-28 05:12:26
【问题描述】:

由于表的关系,我有一组无法成功运行的查询。这个问题已经困扰我一段时间了,我还没有解决它。我见过类似的问题,但无法针对我的情况实施他们的解决方案。

我相信这与我在表中使用的联接类型有关。我曾尝试更改查询中的联接,但它不起作用,因为此时 SQL 联接不明确并且查询不会运行。更正连接和/或使用子查询可能是我需要的解决方案,但是我无法正确实现它。

第一个查询由五个表组成。其目的是为ReportYear 中提供的任何人提供年初至今的总捐赠以及按月细分(我没有列出所有列以节省空间):

tblPartner
    IDPartner (Primary Key) 
    Other demographic info

tblDonation
    ID (Primary Key)
    IDPartner
    Amount
    Other financial info (giving method, designation, etc)

tblChildSponsorship
    ID (Primary Key)
    IDPartner
    Other sponsorship info (level, giving frequency, etc)

tblARBType (this is for tacking online giving, not really important for
            the query but it is nice to have the info displayed)

tblReportParameters (this query holds user input information to specify
    ReportYear       certain parameters of the query like date ranges or
                     donation amounts)

tblPartnertblDonationtblChildSponsorship 具有一对多关系。三个表中的相关字段均为IDPartner

这是我的 Access 中的 SQL:

SELECT 
    tblPartner.IDPartner, 
    IIf([tblPartner.PartnerLastName]="",  tblpartner.PartnerFirstName],[tblPartner.PartnerFirstName] & " " & [tblPartner.PartnerLastName]) AS Partner,
    tblPartner.Organization, IIf([tblARBType.ARBType]="N/A","Check",[tblARBType.ARBType]) AS ARB,
    IIf([Premium]=True,"Premium","Standard") AS SponsorLevel,
    tblPartner.Active,
    tblReportParameters.ReportYear, 
    Year([DateGiven]) AS YYYY,
    Sum(IIf(Month([DateGiven])=1,[Amount],0)) AS Jan,
    Sum(IIf(Month([DateGiven])=2,[Amount],0)) AS Feb,
    Sum(IIf(Month([DateGiven])=3,[Amount],0)) AS Mar,
    Sum(IIf(Month([DateGiven])=4,[Amount],0)) AS Apr,
    Sum(IIf(Month([DateGiven])=5,[Amount],0)) AS May,
    Sum(IIf(Month([DateGiven])=6,[Amount],0)) AS Jun,
    Sum(IIf(Month([DateGiven])=7,[Amount],0)) AS Jul,
    Sum(IIf(Month([DateGiven])=8,[Amount],0)) AS Aug,
    Sum(IIf(Month([DateGiven])=9,[Amount],0)) AS Sep,
    Sum(IIf(Month([DateGiven])=10,[Amount],0)) AS Oct,
    Sum(IIf(Month([DateGiven])=11,[Amount],0)) AS Nov,
    Sum(IIf(Month([DateGiven])=12,[Amount],0)) AS [Dec],
    Sum(IIf(Year([DateGiven]),[Amount],0)) AS YTD
FROM
    tblReportParameters, 
    (
      (
       tblARBType INNER JOIN tblPartner ON tblARBType.ID = tblPartner.ARBType
      ) 
      INNER JOIN tblChildSponsorship ON tblPartner.IDPartner = tblChildSponsorship.IDPartner
    )
    INNER JOIN tblDonation ON tblPartner.IDPartner = tblDonation.IDPartner
GROUP BY tblPartner.IDPartner, 
  IIf([tblPartner.PartnerLastName]="",[tblpartner.PartnerFirstName],[tblPartner.PartnerFirstName] & " " & [tblPartner.PartnerLastName]),
  tblPartner.Organization, 
  IIf([tblARBType.ARBType]="N/A","Check",[tblARBType.ARBType]),
  IIf([Premium]=True,"Premium","Standard"), 
  tblPartner.Active, 
  tblReportParameters.ReportYear,
  Year([DateGiven])
HAVING 
    (((Year([DateGiven]))=[ReportYear]));

我很抱歉那堵文字查询墙。

如果我从查询中删除 tblChildSponsorship,它会返回正确的总和。一旦我添加了该查询,我就会开始得到重复的总数。在我们的系统中,合作伙伴可以赞助多个孩子,因此我认为这是由于加入类型而发生错误的地方。错误金额遵循总和乘以受资助儿童人数的一般模式。

我已经研究过使用DISTINCTDISTINCTROW,但它们都没有改变任何东西,这进一步导致我假设我的连接不好。

如前所述,我已尝试各种子查询来解决此问题,但在尝试更改连接类型时,我最终会遇到相同的结果和问题。

我意识到tblChildSponorship 仅用于一个字段,但是我的第二个查询有一些细微差别,但使用相同的三个具有相同关系结构的主表。如果可以确定一个解决方案,那么它肯定会解决另一个问题。我希望我已经提供了足够的信息,但如果您还需要任何其他信息,请告诉我。

【问题讨论】:

  • 听起来您没有充分加入 tblChildSponsorship,这就是您获得重复总数的原因。检查该表的关键字段是否正确连接。
  • @DaveRlz tblPartner 的 PK 字段是 IDPartner 并连接到其他两个表中相应的 IDPartner 字段。这些字段不是其他两个表中的 PK,因为它们可以在捐赠和赞助表中有多个条目。
  • 花了更多时间查看您的问题,我意识到我不确定您要做什么。 DISTINCT 不起作用,因为您认为实际上是重复的每一行都会有不同的子赞助。我怀疑你的 GROUP BY 是罪魁祸首,你能解释一下你想要达到的目标吗?
  • 此查询的目的是显示年初至今的合作伙伴捐赠。我也希望它打破我一个月的奉献。这使我们能够快速查看捐赠历史,以了解合作伙伴何时退出、何时开始、谁是一致的等。tblChildSponsorship 在查询中仅用于显示赞助级别,即高级或标准。由于这些金额因级别而异,因此我们可以将捐赠金额放在上下文中。另一个查询使用相同的结构,但显示合作伙伴根据受资助的孩子提供 YTD,因此在该查询中返回的合作伙伴列表要小得多。

标签: sql ms-access


【解决方案1】:

考虑将捐赠和赞助拆分为单独的聚合查询,然后将它们合并为一个。因为合作伙伴和儿童赞助共享一对多的关系,所以您不想加入然后在一个流程中聚合,或者将包含加入记录的每个组合(即多个合作伙伴 ID)。因此,只需在合作伙伴级别单独聚合每个集合,然后在最后将两者连接在一起。

合作伙伴捐赠聚合查询 (类似于上面没有 tblChildSponsorship 加入)

SELECT tblPartner.IDPartner, 
    IIf([tblPartner.PartnerLastName]='', tblpartner.PartnerFirstName],
        [tblPartner.PartnerFirstName] & ' ' & [tblPartner.PartnerLastName]) AS Partner,
    tblPartner.Organization, 
    IIf([tblARBType.ARBType]='N/A','Check',[tblARBType.ARBType]) AS ARB,
    tblPartner.Active,
    tblReportParameters.ReportYear, 
    Year([DateGiven]) AS YYYY,
    Sum(IIf(Month([DateGiven])=1,[Amount],0)) AS Jan,
    Sum(IIf(Month([DateGiven])=2,[Amount],0)) AS Feb,
    Sum(IIf(Month([DateGiven])=3,[Amount],0)) AS Mar,
    Sum(IIf(Month([DateGiven])=4,[Amount],0)) AS Apr,
    Sum(IIf(Month([DateGiven])=5,[Amount],0)) AS May,
    Sum(IIf(Month([DateGiven])=6,[Amount],0)) AS Jun,
    Sum(IIf(Month([DateGiven])=7,[Amount],0)) AS Jul,
    Sum(IIf(Month([DateGiven])=8,[Amount],0)) AS Aug,
    Sum(IIf(Month([DateGiven])=9,[Amount],0)) AS Sep,
    Sum(IIf(Month([DateGiven])=10,[Amount],0)) AS Oct,
    Sum(IIf(Month([DateGiven])=11,[Amount],0)) AS Nov,
    Sum(IIf(Month([DateGiven])=12,[Amount],0)) AS [Dec],
    Sum(IIf(Year([DateGiven]),[Amount],0)) AS YTD
FROM tblReportParameters, 
    (tblARBType INNER JOIN tblPartner ON tblARBType.ID = tblPartner.ARBType) 
    INNER JOIN tblDonation ON tblPartner.IDPartner = tblDonation.IDPartner
GROUP BY tblPartner.IDPartner, 
  IIf([tblPartner.PartnerLastName]='', [tblpartner.PartnerFirstName],
      [tblPartner.PartnerFirstName] & ' ' & [tblPartner.PartnerLastName]),
  tblPartner.Organization, 
  IIf([tblARBType.ARBType]='N/A','Check',[tblARBType.ARBType]),
  tblPartner.Active, 
  tblReportParameters.ReportYear,
  Year([DateGiven])
HAVING (((Year([DateGiven]))=[ReportYear]));

赞助聚合查询 (以[Premium]的最新条目)

SELECT IDPartner, Last(IIf([Premium]=True,'Premium','Standard')) AS SponsorLevel,
FROM tblChildSponsorship
GROUP BY IDPartner;

最终加入查询

SELECT d.IDPartner, d.Partner, d.Organization, d.ARB, d.Active, d.ReportYear, d.YYYY
       d.Jan, d.Feb, d.Mar, d.Apr, d.May, d.Jun, 
       d.Jul, d.Aug, d.Sep, d.Oct, d.Nov, d.Dec, d.YTD,
       s.SponsorLevel           
FROM DonationsAgg d
INNER JOIN SponsorshipAgg s
ON d.IDPartner = s.IDPartner

顺便说一句,可以使用派生表(FROMJOIN 子句中的嵌套选择语句)将上述所有查询处理为一个查询。但是 MS Access 允许存储查询,这可能有助于代码源的可维护性。

SELECT DonationsAgg.IDPartner, DonationsAgg.Partner, 
       DonationsAgg.Organization, DonationsAgg.ARB, DonationsAgg.Active, 
       DonationsAgg.ReportYear, DonationsAgg.YYYY
       DonationsAgg.Jan, DonationsAgg.Feb, DonationsAgg.Mar, 
       DonationsAgg.Apr, DonationsAgg.May, DonationsAgg.Jun, 
       DonationsAgg.Jul, DonationsAgg.Aug, DonationsAgg.Sep,
       DonationsAgg.Oct, DonationsAgg.Nov, DonationsAgg.Dec,
       DonationsAgg.YTD, SponsorshipAgg.SponsorLevel
FROM
  (...Partner-Donation Aggregate Query...) As DonationsAgg
INNER JOIN
  (...Sponsorship Aggregate Query...) As SponsorshipAgg
ON DonationsAgg.IDPartner = SponsorshipAgg.IDPartner

【讨论】:

    【解决方案2】:

    这不是最好的选择,但您可以像这样按子数计算总和:

    SELECT 
        ..
        ,Sum(IIf(Month([DateGiven])=1,[Amount],0)) / count(distinct tblChildSponsorship.ID) AS Jan,
        ..
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多