当 PRECEDING 范围为 NULL 时,SQL 移动 AVERAGE() return null ... 超过 1 列

TSQL moving AVG() return null when PRECEDING range is NULL ... more than 1 column

您好,我的 table 中有几列,如果所需的前面的行为空,我希望移动平均线为 return 空。

    CREATE TABLE dbo.TESTMOVINGAVG
(VDATE DATE ,V1 SMALLINT,V2 SMALLINT)

INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-01-2020',4,NULL)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-02-2020',3,NULL)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-03-2020',1,NULL)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-04-2020',9,NULL)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-05-2020',12,NULL)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-06-2020',3,4)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-07-2020',4,8)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-08-2020',15,12)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-09-2020',5,17)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-10-2020',10,9)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-11-2020',14,2)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-12-2020',12,5)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-13-2020',8,6)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-14-2020',7,29)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-15-2020',4,6)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-16-2020',2,8)
INSERT INTO dbo.TESTMOVINGAVG (VDATE,V1,V2) VALUES ('01-17-2020',1,10)

SELECT VDATE,
       V1,
       CASE WHEN ROW_NUMBER() OVER(ORDER BY VDATE ) > 4 AND V1 IS NOT NULL
       THEN
       AVG(V1) OVER (ORDER BY VDATE ASC ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)
       ELSE NULL 
       END AS V1MOVAVG     ,
       CASE WHEN ROW_NUMBER() OVER(ORDER BY VDATE ) > 4 AND V2 IS NOT NULL
       THEN
       AVG(V2) OVER (ORDER BY VDATE ASC ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)
       ELSE NULL 
       END AS V2MOVAVG
FROM TESTMOVINGAVG 

我明白了,

    VDATE   V1  V1MOVAVG    V2MOVAVG
2020-01-01  4   NULL    NULL
2020-01-02  3   NULL    NULL
2020-01-03  1   NULL    NULL
2020-01-04  9   NULL    NULL
2020-01-05  12  5   NULL
2020-01-06  3   5   4
2020-01-07  4   5   6
2020-01-08  15  8   8
2020-01-09  5   7   10
2020-01-10  10  7   10
2020-01-11  14  9   9
2020-01-12  12  11  9
2020-01-13  8   9   7
2020-01-14  7   10  10
2020-01-15  4   9   9
2020-01-16  2   6   10
2020-01-17  1   4   11

但是在 vdate = 01-10-2020 之前我应该​​在 v2movavg 中有空值。当没有空值时,rownumber > 4 适用于 5 的移动平均值。但是,当我的其中一列中有 n 个空值时,我该怎么做呢?

约翰

我想你想要的逻辑是count():

(CASE WHEN COUNT(V2) OVER (ORDER BY VDATE ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) = 5
      THEN AVG (V2) OVER (ORDER BY VDATE ASC ROWS BETWEEN 4 PRECEDING AND CURRENT ROW)
 END) AS V2MOVAVG

我知道您不希望前 4 行中有 null 值。您可以使用 window 计数进行测试:

case when count(v1) over(order by vdate rows between 4 preceding and current row) > 0
    then avg(v1) over(order by vdate rows between 4 preceding and current row)
end as v1movavg

这利用了 count(<expr>) 忽略 null 值这一事实。