【问题标题】:SQL Server - Average preceding Not Null rowsSQL Server - 平均前面的非空行
【发布时间】:2021-02-12 06:46:52
【问题描述】:

我正在尝试对前两行进行简单的平均。复杂的部分是如果一行在 score 列中包含 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   |
    +--------+------------+------------+

【问题讨论】:

  • 我觉得你的输入输出有问题。请检查您的数据,如果需要任何更改,请更新您的问题。我会很容易检查。
  • 它只需要作为一个查询运行。我已经消除了数据和 SELECT 查询之间的差距。谢谢。

标签: sql sql-server-2017


【解决方案1】:

您可以使用带有顶级子句的子查询:

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

【讨论】:

  • 这是最好的选择。我希望避免这种情况,因为我需要重写大量代码,但看起来下一个“x”非空行并不容易平均。
  • 是的,抱歉,使用LAST_VALUE 您可以获得最后一个非空值,但没有功能可以让您获得倒数第二个。我认为 SQL Server 中没有任何内置的东西可以在这里提供帮助。
【解决方案2】:

我不熟悉 MSSQL,但这可能工作。

您可以在使用窗口函数之前尝试将表格包装在 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
;

【讨论】:

  • 它不会给出想要的答案,因为它会返回NULL 日期2020-06-01
  • 谢谢。这是我可能不得不选择的那种选择。问题是我在同一个 SELECT 语句中有数百个不同的平均值和总和,因此试图看到(“希望”)有一个简单的解决方案,而无需重写所有代码。
猜你喜欢
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多