从MS Access中的多个表中总计总计

时间:2017-07-19 23:57:35

标签: ms-access

民间。我似乎找不到这个问题的答案。我可以在SQL Server中完成,但我现在正在使用Access 2013,而我通常的SQL技巧似乎不起作用。

我需要创建一个课程成本v。收入摘要报告。

我有三个表:班级列表,成本列表,注册列表。成本和注册(成本和收入)都通过在所有表中标识该类的关键字段与类列表相关联。

我能够运行成本报告或收入报告,并且每个班级的总数都很好,但是当我将它们组合起来获得每个班级的净额时,成本会乘以注册报告中的行数反之亦然。

我尝试过使用Outer Join,但访问不喜欢它,即使在正确的位置使用[]也是如此。最好将其保持在访问状态,因为远离excel是重点。

tables and expected results

incorrect results

这是糟糕结果背后的SQL。我知道这些连接是错误的,但我无法接受任何其他类型的连接。

SELECT DISTINCTROW Classes.ID,
       Classes.Title,
       Classes.Instructor,
       Classes.Date,
       Sum(Costs.Amount) AS [Sum Of Amount],
       Sum(Registrations.Tuition) AS [Sum Of Tuition],
       Count(*) AS [Count Of Classes]
FROM (Classes
      LEFT JOIN Registrations ON Classes.[ID] = Registrations.[Class ID])
LEFT JOIN Costs ON Classes.[ID] = Costs.[Class ID]
GROUP BY Classes.ID,
         Classes.Title,
         Classes.Instructor,
         Classes.Date;

有什么建议吗?提前谢谢。

1 个答案:

答案 0 :(得分:0)

您需要两个单独的查询来汇总不同表的值,即使它们已连接到同一主表。否则,SQL的选择部分将在另外两个表上执行交叉连接,有效地为每个注册重新选择每个成本值。该选择过程在分组和聚合(即总和,计数)之前发生。这就是你得到乘以总和的原因。

DISTINCTROW无效,因为查询是根据连接中每个表的字段选择值,因此它必须有效地保留原始集中的每一行。 DISTINCTROW 首先从一个表中选择行,然后从另一个表中独立选择行(也不单独对它们求和)。相反,应用完整选择和交叉连接,然后通过询问&#34来过滤掉行;此行是否仅包含来自已选择的源表行的数据?"如果答案是肯定的,则将其从最终选择中排除。但是,如果所选数据包含联接中每个表的值,则每一行都是唯一的,因此不会排除任何内容。

定义一个总和:

SELECT Classes.ID As ID,
       Sum(Costs.Amount) AS [Sum Of Amount]
FROM Classes
     LEFT JOIN Costs 
     ON Classes.[ID] = Costs.[Class ID]
GROUP BY Classes.ID

然后另一个:

SELECT Classes.ID As ID,
       Sum(Registrations.Tuition) AS [Sum Of Tuition]
FROM Classes
     LEFT JOIN Registrations ON Classes.[ID] = Registrations.[Class ID]
GROUP BY Classes.ID

您可以在Access中保存这些查询,然后按名称在其他查询中引用它们,或者您可以包含嵌入式SQL。在这种情况下,它只是个人偏好,但是使用可视化设计视图无法检查或编辑嵌入式查询,而是必须使用Access中的SQL视图进行编辑。

SELECT DISTINCTROW Classes.ID, Classes.Title,
       Classes.Instructor, Classes.Date,
       CostsAgg.[Sum Of Amount],
       RegAggs.[Sum Of Tuition]
FROM (Classes LEFT JOIN
      (SELECT Classes.ID As ID, Sum(Costs.Amount) AS [Sum Of Amount]
       FROM Classes LEFT JOIN Costs ON Classes.[ID] = Costs.[Class ID]
       GROUP BY Classes.ID) AS CostsAgg ON Classes.ID = CostsAgg.ID)
      LEFT JOIN 
        (SELECT Classes.ID As ID, Sum(Registrations.Tuition) AS [Sum Of Tuition]
         FROM Classes LEFT JOIN Registrations ON Classes.[ID] = Registrations.[Class ID]
         GROUP BY Classes.ID) AS RegAggs
      ON Classes.ID = RegAggs.ID
GROUP BY Classes.ID,
         Classes.Title,
         Classes.Instructor,
         Classes.Date;

我没有包含Count列,因为从示例中不清楚你真正想要计算什么。您当然可以在任何子/查询中单独包含一个Count字段,或者在所有子/查询中分别包含一个Count字段,以获得不同的值。