使用 LAG Window 函数在 Oracle 中按记录计算剩余总计

Posted

技术标签:

【中文标题】使用 LAG Window 函数在 Oracle 中按记录计算剩余总计【英文标题】:Calculate Remaining Total by Record in Oracle Using LAG Window Function 【发布时间】:2017-10-23 19:45:44 【问题描述】:

我很难使用 LAG 窗口函数来制作我最能描述为使用 Oracle 12 的总账的分类账。我已将问题抽象如下:

我有一架固定座位数的客机,但有时航班超卖。我试图通过使用累计总数来确定谁得到了一张票,谁没有。

对于每位乘客 (PASS),我已按类别(1=1 等舱,2=经济舱)和其中的优先级(谁先下单)对数据进行排序。

在 REM 列中,我试图计算剩余的座位总数。我假设每张 PASS 只占一个座位,而且我每个班级都有固定数量的 AVAIL 座位。该乘客就座后剩余的座位 (REM) 将在分区中的每个用户减少一个。期望的结果如下所示:

PASS |PRI|CLASS|AVAIL|REM
User9 1   1     2     1
User1 4   1     2     0
User8 2   2     3     2
User4 3   2     3     1
User3 5   2     3     0
USER2 6   2     3     -1

我一直在尝试这样做:

SELECT 
    PASS, PRI, CLASS,
    LAG(AVAIL, 1, AVAIL) OVER (PARTITION BY CLASS ORDER BY CLASS, PRI) - 1 AS REM
FROM TABLE
ORDER BY CLASS, PRI

但我的 REM 最终数据有误:

PASS |PRI|CLASS|AVAIL|REM
User9 1   1     2     1
User1 4   1     2     1
User8 2   2     3     2
User4 3   2     3     2
User3 5   2     3     2
USER2 6   2     3     2

我的窗口函数显然处理了这个错误,因为它在分区中寻找下一个 AVAIL 记录并减去一个,但 AVAIL 没有改变,所以我在整个分区中得到相同的 REM 值。

如何让 REM 从分区中的 AVAIL 中减去 1,然后在下一行中为 AVAIL 使用该新值?

【问题讨论】:

【参考方案1】:

这似乎与您的描述相符:

AVAIL 
- Count(*)
  Over (PARTITION BY CLASS 
        ORDER BY PRI ROWS Unbounded Preceding)

可用座位减去每个班级的累积行数。

并且累积计数等于 ROW_NUMBER:

AVAIL 
- ROW_NUMBER()
  Over (PARTITION BY CLASS 
        ORDER BY PRI)

【讨论】:

明白了,谢谢!但是,为什么这行得通? @SandPiper:看看独立 ROW_NUMBER/COUNT 的结果。您的 LAG 方法不起作用,因为计算是基于上一行的 数据,而不是上一行的 计算结果【参考方案2】:

只需从avail 列中减去运行总和。

SELECT PASS, PRI, CLASS, AVAIL,
avail-sum(1) over(partition by class order by pri) AS REM
FROM TABLE

【讨论】:

虽然这个答案也有效,但我将另一个答案标记为已接受,因为我更容易将它从抽象中扩展回我的真实项目。谢谢!

以上是关于使用 LAG Window 函数在 Oracle 中按记录计算剩余总计的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE 偏移分析函数 lag()与lead() 用法

ORACLE 偏移分析函数 lag()与lead() 用法

如何在 oracle pl sql 中使用 LAG 函数,直到到达非零或最后一行?

Oracle 中的 LAG 函数

Oracle SQL LAG 函数

基于其他两列并使用 LAG 函数更新 Oracle 过程中的列