如何在不包括最后一个值(sql)的情况下计算值的平均值?

Posted

技术标签:

【中文标题】如何在不包括最后一个值(sql)的情况下计算值的平均值?【英文标题】:How to calculate average of values without including the last value (sql)? 【发布时间】:2020-11-26 14:58:00 【问题描述】:

我有一张桌子。我按 id 对其进行分区,并希望计算当前值之前的平均值,而不包括当前值。这是一个示例表:

+----+-------+------------+
| id | Value |    Date    |
+----+-------+------------+
|  1 |    51 | 2020-11-26 |
|  1 |    45 | 2020-11-25 |
|  1 |    47 | 2020-11-24 |
|  2 |    32 | 2020-11-26 |
|  2 |    51 | 2020-11-25 |
|  2 |    45 | 2020-11-24 |
|  3 |    47 | 2020-11-26 |
|  3 |    32 | 2020-11-25 |
|  3 |    35 | 2020-11-24 |
+----+-------+------------+

在这种情况下,这意味着计算 2020 年 11 月 26 日之前日期的平均值。这是预期的结果

+----+-------+
| id | Value |
+----+-------+
|  1 |    46 |
|  2 |    48 |
|  3 |  33.5 |
+----+-------+

我已经使用ROWS N PRECEDING 计算了它,但似乎这样我平均前 N 个 + 最后一行,我想排除最后一行(在我的情况下这是最近的日期)。 这是我的查询:

SELECT ID, 
  (avg(Value) OVER(
      PARTITION BY ID
      ORDER BY Date
      ROWS 9 PRECEDING )) as avg9
FROM t1

【问题讨论】:

【参考方案1】:

然后使用BETWEEN 开头和结尾来完整定义您的窗口:

SELECT ID,
       (AVG(Value) OVER (PARTITION BY ID ORDER BY Date ROWS BETWEEN 9 PRECEDING AND 1 PRECEDING)) AS avg9
FROM t1;

【讨论】:

这再简单不过了……我只是在最后 30 分钟里受苦……谢谢!【参考方案2】:

为什么不直接过滤:

select id, avg(value)
from t1
where date < '2020-11-26'
group by id;

如果您希望日期灵活——说出每个日期的最新值,那么:

select id, avg(value)
from (select t1.*,
             max(date) over (partition by id) as max_date
      from t1
     ) t1
where date < max_date
group by id;

【讨论】:

【参考方案3】:

对(按 id ORDER BY [Date] DESC 分区)执行 row_number()。这将为具有最新日期的行提供 rank = 1。将其包装在 CTE 中,然后计算 RANK > 1 的每个分区的 avg。请检查语法。

;with a as
(
select id, value, Date, row_number() over (partition by id order by date 
desc) as RN
)
select id, avg(Value) from a group by id where r.RN > 1 

【讨论】:

以上是关于如何在不包括最后一个值(sql)的情况下计算值的平均值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不插入值的情况下在sql中创建动态行?

在不向行/列添加值的情况下计算 SUM?

如何在不指定键值的情况下获取 JSON 对象的最后一个元素?

在不知道输入数量的情况下计算最小、最大和平均输入值的最佳方法? [关闭]

如何在不使用乘法的情况下对数字进行平方?

在不知道 SQL 中的列的情况下创建表