SQL 服务器 - 前面的非空行的平均值
SQL Server - Average preceding Not Null rows
我正在尝试对前两行进行简单平均。复杂的部分是如果一行在分数列中包含 NULL,我想对最后 2 个 NON NULL 行求平均值。
按非空排序不起作用,因为它将当前行与其余非空行放在一起。类似地,创建一个单独的非空行号会产生同样的问题。我假设我必须通过外部连接来解决,但只是检查是否有人知道对以下代码进行更简单的调整。
示例数据:
DECLARE @tbl TABLE
(
Team varchar(1),
date date,
Score int
);
INSERT INTO @tbl (Team, Date, Score)
VALUES
('a', '2020/12/05', null),
('a', '2020/12/04', null),
('a', '2020/12/03', null),
('a', '2020/12/02', null),
('a', '2020/11/04', '2'),
('a', '2020/10/03', '4'),
('a', '2020/08/02', '6'),
('a', '2020/06/01', '8');
SELECT
date,
avg(SCORE+0.0) OVER (partition by Team ORDER BY Date ASC ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) AS Average
FROM
@tbl
ORDER BY
Date DESC
输出:
+--------+------------+------------+
| Row | Current | Required |
+--------+------------+------------+
| 1 | NULL | 3 |
| 2 | NULL | 3 |
| 3 | 2 | 3 |
| 4 | 3 | 3 |
| 5 | 5 | 5 |
| 6 | 7 | 7 |
| 7 | 8 | 8 |
| 8 | NULL | NULL |
+--------+------------+------------+
我不熟悉 MSSQL,但这可能有效。
您可以尝试在使用 Window 函数之前将 table 包装在 CTE 中,例如
WITH tbl_CTE (Team, Date, Score)
AS
(
SELECT *
FROM @tbl
WHERE Score IS NOT NULL
)
SELECT
date,
avg(SCORE+0.0) OVER (partition by Team ORDER BY Date ASC ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) AS Average
FROM
tbl_CTE
ORDER BY
Date DESC
;
您可以使用带有 top 子句的子查询:
SELECT
date,
(
SELECT AVG(score+0.0)
FROM
(
SELECT TOP(2) score
FROM @tbl t2
WHERE t2.date < t1.date
AND t2.score IS NOT NULL
ORDER BY t2.date DESC
) two_previous
) as average
FROM @tbl t1
ORDER BY date DESC;
演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=5ad91643b0fa21fe8a78b78ded1ce498
我正在尝试对前两行进行简单平均。复杂的部分是如果一行在分数列中包含 NULL,我想对最后 2 个 NON NULL 行求平均值。
按非空排序不起作用,因为它将当前行与其余非空行放在一起。类似地,创建一个单独的非空行号会产生同样的问题。我假设我必须通过外部连接来解决,但只是检查是否有人知道对以下代码进行更简单的调整。
示例数据:
DECLARE @tbl TABLE
(
Team varchar(1),
date date,
Score int
);
INSERT INTO @tbl (Team, Date, Score)
VALUES
('a', '2020/12/05', null),
('a', '2020/12/04', null),
('a', '2020/12/03', null),
('a', '2020/12/02', null),
('a', '2020/11/04', '2'),
('a', '2020/10/03', '4'),
('a', '2020/08/02', '6'),
('a', '2020/06/01', '8');
SELECT
date,
avg(SCORE+0.0) OVER (partition by Team ORDER BY Date ASC ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) AS Average
FROM
@tbl
ORDER BY
Date DESC
输出:
+--------+------------+------------+
| Row | Current | Required |
+--------+------------+------------+
| 1 | NULL | 3 |
| 2 | NULL | 3 |
| 3 | 2 | 3 |
| 4 | 3 | 3 |
| 5 | 5 | 5 |
| 6 | 7 | 7 |
| 7 | 8 | 8 |
| 8 | NULL | NULL |
+--------+------------+------------+
我不熟悉 MSSQL,但这可能有效。
您可以尝试在使用 Window 函数之前将 table 包装在 CTE 中,例如
WITH tbl_CTE (Team, Date, Score)
AS
(
SELECT *
FROM @tbl
WHERE Score IS NOT NULL
)
SELECT
date,
avg(SCORE+0.0) OVER (partition by Team ORDER BY Date ASC ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) AS Average
FROM
tbl_CTE
ORDER BY
Date DESC
;
您可以使用带有 top 子句的子查询:
SELECT
date,
(
SELECT AVG(score+0.0)
FROM
(
SELECT TOP(2) score
FROM @tbl t2
WHERE t2.date < t1.date
AND t2.score IS NOT NULL
ORDER BY t2.date DESC
) two_previous
) as average
FROM @tbl t1
ORDER BY date DESC;
演示:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=5ad91643b0fa21fe8a78b78ded1ce498