当 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
值这一事实。
您好,我的 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
值这一事实。