如何在不包括最后一个值(sql)的情况下计算平均值?
How to calculate average of values without including the last value (sql)?
我有一个table。我按 id 对其进行分区,并希望计算当前值之前的值的平均值,但不包括当前值。这是一个示例 table:
+----+-------+------------+
| 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
为什么不直接过滤:
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;
然后使用 BETWEEN
:
开始和结束来完整定义您的 window
SELECT ID,
(AVG(Value) OVER (PARTITION BY ID ORDER BY Date ROWS BETWEEN 9 PRECEDING AND 1 PRECEDING)) AS avg9
FROM t1;
执行 row_number() over(按 id ORDER BY [Date] DESC 分区)。这将为具有最新日期的行提供 rank = 1。将其包装在 CTE 中,然后计算 RANK > 1 的每个分区的平均值。请检查语法。
;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
我有一个table。我按 id 对其进行分区,并希望计算当前值之前的值的平均值,但不包括当前值。这是一个示例 table:
+----+-------+------------+
| 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
为什么不直接过滤:
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;
然后使用 BETWEEN
:
SELECT ID,
(AVG(Value) OVER (PARTITION BY ID ORDER BY Date ROWS BETWEEN 9 PRECEDING AND 1 PRECEDING)) AS avg9
FROM t1;
执行 row_number() over(按 id ORDER BY [Date] DESC 分区)。这将为具有最新日期的行提供 rank = 1。将其包装在 CTE 中,然后计算 RANK > 1 的每个分区的平均值。请检查语法。
;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