sqlite 触发器中的窗口函数Lag()使用缺省值而不是以前的值

fwzugrvs  于 2022-11-15  发布在  SQLite
关注(0)|答案(1)|浏览(213)

我正在尝试创建一个SQLite触发器来更新特定帐户codebalance
accounts表:

CREATE TABLE accounts (
    year      INTEGER   NOT NULL,
    month     INTEGER   NOT NULL   CHECK(month BETWEEN 1 AND 12),
    amount    REAL      NOT NULL   CHECK(amount >= 0),
    balance   REAL,
    code      INTEGER   NOT NULL
);

当插入新行时,我希望新行的balance值反映OLD balance + NEW amount。但是这个触发器不能识别滞后的balance值,我想不出原因:

CREATE TRIGGER trg_accounts_balance
AFTER INSERT ON accounts
BEGIN
    UPDATE accounts
    SET balance = (
        SELECT
            lag(balance, 1, 0) OVER (
                PARTITION BY code
                ORDER BY month
            ) + NEW.amount
        FROM accounts
    )
    WHERE rowid = NEW.ROWID;
END;

如果我每月插入一行,我希望我的数据如下所示:
年|月|金额|余额|编码
-|
2022年|1|100.0|100.0|100
2022年|2|9.99|109.99|100
但我得到了:
年|月|金额|余额|编码
-|
2022年|1|100.0|100.0|100
2022|2|9.99|9.99|100
我做错了什么?

rhfm7lfc

rhfm7lfc1#

查询:

SELECT
    lag(balance, 1, 0) OVER (
                PARTITION BY code
                ORDER BY month
            ) 
FROM accounts

返回表中的所有行,SQLite选择第一行(无论是哪一行)将其作为结果返回,以便它可以使用它来添加NEW.amount
没有任何内容将此值链接到插入的特定行。
相反,请使用以下命令:

CREATE TRIGGER trg_accounts_balance
AFTER INSERT ON accounts
BEGIN
    UPDATE accounts
    SET balance = COALESCE(
       (
        SELECT balance
        FROM accounts
        WHERE code = NEW.code
        ORDER BY year DESC, month DESC
        LIMIT 1, 1
       ), 0)  + NEW.amount
    WHERE rowid = NEW.ROWID;
END;

子查询通过对特定code的行进行降序排序并跳过顶行(即新行)来返回先前插入的行。
请参阅demo

相关问题