在VIEW中的SUM OVER PARTITION BY为NULL,但在直接使用时可以正常工作

时间:2017-10-03 17:35:51

标签: sql-server

在SQL Server 2016数据库中,我有一个包含财务事务的表:

CREATE TABLE Transactions
    TxnId     int      NOT NULL IDENTITY(1,1) PRIMARY KEY,
    AccountId int      NOT NULL,
    DateTime  datetime NOT NULL,
    Amount    money    NOT NULL
)

我写了一个VIEW来显示运行余额信息:

CREATE VIEW TransactionsWithBalance AS

SELECT
    *,
    SUM( Amount ) OVER ( PARTITION BY AccountId ORDER BY [DateTime], TxnId ) AS Balance
FROM
    Transactions

当我查询此视图时,Balance列包含所有NULL值:

SELECT
    *
FROM
    TransactionsWithBalance

TxnId    AccountId    DateTime      Amount    Balance
    1            1    2017-01-01    100.00    NULL
    2            1    2017-01-02    200.00    NULL
    3            2    2017-01-01     10.00    NULL
    4            1    2017-01-03    300.00    NULL

但是当我在SSMS中直接运行查询(使用SUM( Amount ) OVER ( PARTITION BY... ))查询时,我会在Balance列中获得预期值。

TxnId    AccountId    DateTime      Amount    Balance
    1            1    2017-01-01    100.00     100.00
    2            1    2017-01-02    200.00     300.00
    3            2    2017-01-01     10.00      10.00
    4            1    2017-01-03    300.00     600.00

为什么在NULL内查询时汇总返回VIEW值?

1 个答案:

答案 0 :(得分:4)

这是元数据不同步时可能发生的事情之一,因为您没有:

  • 架构绑定视图;或
  • 只要视图底层的对象发生变化,就调用sp_refreshview

      

    说明

         

    如果未使用模式绑定创建视图,则在对视图下方影响视图定义的对象进行更改时,应运行 sp_refreshview 。否则,查询时视图可能会产生意外结果。

更好的选择可能是使用架构绑定。这也将迫使您不在视图中使用SELECT *,并为表格使用两部分名称,这两种方法都是最佳做法:

CREATE VIEW dbo.TransactionsWithBalance
WITH SCHEMABINDING
AS
SELECT
    TRN.TxnId, 
    TRN.AccountId,
    TRN.[DateTime],
    TRN.Amount,
    Balance =
        SUM(TRN.Amount) OVER (
            PARTITION BY TRN.AccountId 
            ORDER BY TRN.[DateTime], TRN.TxnId)
FROM
    dbo.Transactions AS TRN;