【问题标题】:Fastestest way of calculating Running Totals in SQL在 SQL 中计算运行总计的最快方法
【发布时间】:2020-03-23 14:50:45
【问题描述】:

我想计算我的选择查询的每一行中的运行总计,以便我可以根据该总计过滤返回的行。在我看来,我只有两个选择。

  1. 在 select 语句中使用 over 并使主查询成为子查询

例子:

SELECT DocDate,
       Debit,
       RunningTotal
FROM
(
    SELECT T1.DocDate,
           T1.Debit,
           SUM(T1.Debit) OVER(ORDER BY T1.DocDate DESC) AS RunningTotal
        FROM Invoices T1
) AS T
WHERE RunningTotal < @CurrentBalance 
  1. Join 自己的桌子

例子:

SELECT T1.DocDate,
       T1.Debit,
       SUM(T2.Debit) AS RunningTotal
FROM Invoices T1
JOIN Invoices T2 ON T1.DocDate <= T2.DocDate
GROUP BY T1.DocDate,
   T1.Debit
   HAVING SUM(T2.Debit) < @CurrentBalance
ORDER BY T1.DocDate DESC

两个查询返回完全相同的结果。不过,在性能方面,建议的方法是什么?

【问题讨论】:

  • 一般来说,窗口函数会比更复杂的方法更快。
  • @i_ll_be_back - SQL 不是直接执行的,而是被执行并形成一个“执行计划”;很像编译代码。事实上,例如比较 C 和 SQL; C 是命令式的,而 SQL 是声明式的,这意味着数据库引擎在如何实现您声明的功能需求方面有更广泛的选择。因此,简而言之,编写嵌套查询不一定会导致跨数据的多次迭代。它只是一种表达功能的机制。但是以通常描述的方式加入数据确实会产生明显的开销。

标签: sql sql-server performance cumulative-sum


【解决方案1】:

除非您的表格的行数太少以至于您可以一方面计算它们,否则内置的窗口函数会更快。

为什么?首先,它是为此目的而内置和设计的。

其次,它实际上计算了一个累积和。因此,在计算第 10 个值时,它是使用第 9 个累积和的结果,然后再添加一个值。

join 方法是一种特别糟糕的计算方式。如果表中有 100 行,那么它将表扩展为 100 * 99 / 2 行(给予或接受)——然后必须聚合超过 100 行。您可以看到,随着您的桌子变大,这种情况会变得更糟。

也就是说,如果表中有三行,您可能会发现连接效果更好。这就是大数定律:有时会在小数上发生令人惊讶的事情。

【讨论】:

  • 很好的解释!我的表包含数千行,所以我猜想和子查询是要走的路。
猜你喜欢
  • 2023-03-23
  • 2010-10-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
相关资源
最近更新 更多