【问题标题】:Aggregate query in MS-Access that calculates current and cumulative amounts by account is exceptionally slowMS-Access 中按帐户计算当前和累计金额的聚合查询异常缓慢
【发布时间】:2020-02-25 19:14:32
【问题描述】:

我在使用 Access 查询时遇到问题。虽然它运行,但它异常慢;而且我担心我可能会在我的查询设计中忽略一个更简单、更优雅的解决方案。

就上下文而言,我在应收账款办公室工作。我们有成千上万的客户,每个客户可以拥有一个或多个帐户。每个月,交易都会发布到各个帐户,我正在为客户准备发票。在我的特定情况下,客户的第一张发票始终是 001,然后是 002,依此类推。我们按月计费。

为了描述一个简化的示例,在 2020 年 1 月,客户 A 在 Transaction 表中可能有以下交易:

+------------------------------+ |TransID|账户|金额|InvNum| +------------------------------+ |1 |1 |$10.00|001 | |2 |2 |$5.00 |001 | |3 |3 |$2.00 |001 | +------------------------------+

因此,在上面的示例中,我想向客户 A 开具发票 001,总金额为 17.00 美元,按帐户细分。发票看起来像这样:

+------------------------+ |帐户|当前|ToDate | |1 |$10.00 |$10.00 | |2 |$5.00 |$5.00 | |3 |$2.00 |$2.00 | +------------------------+ $17.00 $17.00

现在,假设在 2020 年 2 月发布了额外的交易。 Transaction 表的简化版本如下所示:

+------------------------------+ |TransID|账户|金额|InvNum| +------------------------------+ |1 |1 |$10.00|001 | |2 |2 |$5.00 |001 | |3 |3 |$2.00 |001 | |4 |1 |$3.00 |002 | |5 |3 |$4.00 |002 | +------------------------------+

发给客户 A 的发票 #002 需要如下所示:

+------------------------+ |帐户|当前|ToDate | |1 |$3.00 |$13.00 | |2 |$0.00 |$5.00 | |3 |$4.00 |$6.00 | +------------------------+ $7.00 $24.00

我遇到问题的查询专门用于按帐户捕获当月的活动,以计算发票上“ToDate”列的累积总数。挑战在于,并非每个账户都会在给定月份进行交易。请注意,账户 2 在 2 月份没有发布任何交易。因此,发票 002 必须显示帐户 2 的当前金额 0.00 美元,但它还需要知道帐户 2 的累计金额 ($5.00 + $0.00 = $5.00)。

有问题的查询本身由几个子查询组成:

  1. BillNumByAccountQ:按发票编号选择和分组所有帐户的聚合查询。
  2. CurrentQ:也是一个聚合查询,它选择并汇总所有交易金额(来自交易表),左连接到 BillNumByAccountQ。左连接对于确保每个账单编号都有一行是必要的。此查询中的“当前”字段由表达式 Sum(Nz(Amount,0)) 给出。此查询的结果集包含超过 20K 行。

最后,有问题的查询由以下 SQL 语句定义:

SELECT 
   Q1.Account
    ,Q1.InvNum
    ,Q1.CURRENT
    ,(
        SELECT SUM(CURRENT)
        FROM CurrentQ
        WHERE Q1.Account = Account
            AND Q1.InvNum >= InvNum
        ) AS ToDate
FROM CurrentQ AS Q1;

此查询运行、运行和运行,最终导致 Access 停止响应。我什至不知道它有多少行,因为它永远不会完成运行。我担心我忽略了一种更简单的解决方案。

抱歉提供了这么多信息,我很感激任何关于简化这一点的建议。

【问题讨论】:

  • 请显示查询的底层 SQL:CurrentQBillNumByAccountQ。尝试将 CurrentQ 保存为临时表并在此表上运行最终查询。

标签: sql performance ms-access


【解决方案1】:

通常,在 select 语句中执行子查询很慢,因为它通常需要为主查询的每一行运行子查询。

一次进行所有聚合可能会更快:

SELECT 
     Q1.Account
    ,Q1.InvNum
    ,Q1.CURRENT
    ,SUM(i.CURRENT) AS ToDate
FROM CurrentQ AS Q1
JOIN CurrentQ AS i
     ON  i.Account = Q1.Account
     AND i.InvNum >= Q1.InvNum
GROUP BY Q1.Account, Q1.InvNum, Q1.Current;

此外,如果您能够编辑数据库,您可能希望为 AccountInvNum 列添加索引。

【讨论】:

  • 谢谢!通过一些小的调整,这个解决方案真的节省了一天!我需要学习很多关于 SQL 并使其更高效的知识,因此您对如何为每一行运行子查询的解释很有意义。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 2016-03-27
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多