【发布时间】:2015-11-04 12:26:38
【问题描述】:
我在 SQL Server 中有一个临时表,如下所示
╔═══════╦═════════╦══════╦═════════╗
║Serial ║ Account ║ Due ║ Balance ║
║1 ║ A1 ║ 1000 ║ 3100 ║
║2 ║ A1 ║ 1000 ║ 3100 ║
║3 ║ A1 ║ 1000 ║ 3100 ║
║4 ║ A1 ║ 1000 ║ 3100 ║
║1 ║ A2 ║ 100 ║ 3100 ║
║2 ║ A2 ║ 100 ║ 3100 ║
║1 ║ B1 ║ 1000 ║ 1100 ║
║2 ║ B1 ║ 1000 ║ 1100 ║
║1 ║ B2 ║ 100 ║ 1100 ║
║2 ║ B2 ║ 100 ║ 1100 ║
╚═══════╩═════════╩══════╩═════════╝
我想确定应收集的行。 A1 和 A2 到期将从 3100 收取,B1 和 B2 到期将从 1100 收取。
首先我使用累积到期如下
╔═══════╔═════════╦══════╦════════════╦═════════╦
║Serial ║ Account ║ Due ║ Cumulative ║ Balance ║
║1 ║ A1 ║ 1000 ║ 1000 ║ 3100 ║
║2 ║ A1 ║ 1000 ║ 2000 ║ 3100 ║
║3 ║ A1 ║ 1000 ║ 3000 ║ 3100 ║
║4 ║ A1 ║ 1000 ║ 4000 ║ 3100 ║
║1 ║ A2 ║ 100 ║ 100 ║ 3100 ║
║2 ║ A2 ║ 100 ║ 200 ║ 3100 ║
║1 ║ B1 ║ 1000 ║ 1000 ║ 1100 ║
║2 ║ B1 ║ 1000 ║ 2000 ║ 1100 ║
║1 ║ B2 ║ 100 ║ 100 ║ 1100 ║
║2 ║ B2 ║ 100 ║ 200 ║ 1100 ║
╚═══════╚═════════╩══════╩════════════╩═════════╝
现在我想选择以下行作为输出
╔═══════╔═════════╦══════╦════════════╦═════════╦
║Serial ║ Account ║ Due ║ Cumulative ║ Balance ║
║1 ║ A1 ║ 1000 ║ 1000 ║ 3100 ║
║2 ║ A1 ║ 1000 ║ 2000 ║ 3100 ║
║3 ║ A1 ║ 1000 ║ 3000 ║ 3100 ║
║1 ║ A2 ║ 100 ║ 100 ║ 3100 ║
║1 ║ B1 ║ 1000 ║ 1000 ║ 1100 ║
║1 ║ B2 ║ 100 ║ 100 ║ 1100 ║
╚═══════╚═════════╩══════╩════════════╩═════════╩
这是我卡住的地方。如何在不使用游标或循环的情况下选择这些行。我只想用 select 语句和窗口函数来做这件事。 谢谢。
可能的解决方案:如果表格可以更新如下,那么问题就解决了。
╔═══════╔═════════╦══════╦═══════════════════╦
║Serial ║ Account ║ Due ║ Balance Remaining ║
║1 ║ A1 ║ 1000 ║ 3100 ║
║2 ║ A1 ║ 1000 ║ 2100 ║
║3 ║ A1 ║ 1000 ║ 1100 ║
║4 ║ A1 ║ 1000 ║ 100 ║
║1 ║ A2 ║ 100 ║ 100 ║
║2 ║ A2 ║ 100 ║ 0 ║
║1 ║ B1 ║ 1000 ║ 1100 ║
║2 ║ B1 ║ 1000 ║ 100 ║
║1 ║ B2 ║ 100 ║ 100 ║
║2 ║ B2 ║ 100 ║ 0 ║
╚═══════╚═════════╩══════╩═══════════════════╩
Balance Remaining 等于/大于 Due 的情况,我们会更新差异,否则它将保持原样。问题在于通过 A 和 B 之间的分区来更新行。
更新 我正在提供与新数据集的链接,以更清楚地表达我的要求。 new dataset
【问题讨论】:
-
SQL Server 的哪个版本?
-
SQL SERVER 2012 或更高版本。
-
问题是即使SQL Server 2012提供了强大的窗口函数,也没有条件累加的好方法。换句话说,根据之前的总额是否大于余额,有条件地为总和做出贡献。基于光标的解决方案可能是最简单和最有效的 - 为什么不想要基于光标的解决方案?
-
对于大数据集游标/while循环都变慢了。
-
Yes cursors/while 循环在 99% 的情况下是最糟糕的解决方案。但是,在您需要计算运行总计或余额的情况下,基于集合并不总是答案。事实上,由于条件(不允许余额低于 0),我什至不确定是否可以使用基于集合/窗口的函数(或者如果是,它实际上可能慢得多 不是光标)。这将是 1% 的情况之一,其中游标可能是最佳解决方案(请参阅 sqlperformance.com/2012/07/t-sql-queries/running-totals 和 stackoverflow.com/a/11313533/116614)。
标签: sql sql-server