我的目标是仅当满足另一个表的左连接条件时才平均选择恰好 5 条记录。 假设我们有表一(左)包含记录:
RECNUM ID DATE JOB
1 | cat | 2019.01.01 | meow
2 | dog | 2019.01.01 | bark
我们有表二(右)包含记录:
RECNUM ID Action_ID DATE REWARD
1 | cat | 1 | 2019.01.02 | 20
2 | cat | 99 | 2018.12.30 | 1
3 | cat | 23 | 2019.12.28 | 20
4 | cat | 54 | 2018.01.01 | 20
5 | cat | 32 | 2018.01.02 | 20
6 | cat | 21 | 2018.01.03 | 20
7 | cat | 43 | 2018.12.28 | 1
8 | cat | 65 | 2018.12.29 | 1
9 | cat | 87 | 2018.09.12 | 1
10 | cat | 98 | 2018.10.11 | 1
11 | dog | 56 | 2018.09.01 | 99
12 | dog | 42 | 2019.09.02 | 99
结果应该返回:
ID | AVG(Reward_from_latest_5_jobs)
cat | 1
满足的标准应该是: 对于左表中的每个作业,尝试在右表中查找相同 ID 的 5 个最新但较旧的唯一 Action_ID,并计算它们的平均值。 换句话说,狗叫了,我们不知道该给他什么奖励,我们尝试计算他最近获得的五个奖励的平均值。 如果找到的少于 5 个,则不返回任何内容/置 null,如果超过,则丢弃最旧的。
我想要的方式是这样的:
SELECT a."ID", COUNT(b."Action_ID"), AVG(b."REWARD")
FROM
(
SELECT "ID", "DATE"
FROM :left_table
) a
LEFT JOIN
(
SELECT "ID", "Action_ID", "DATE", "REWARD"
FROM :right_table
) b
ON(
a."ID" = b."ID"
)
WHERE a."DATE" > b."DATE"
GROUP BY a."ID"
HAVING COUNT(b."Action_ID") >= 5;
但是它会计算所有符合条件的 Action_ID,而不仅仅是最近的五个。请您介绍一下如何达到预期效果?我可以使用子表,并且不必在一条 SQL 语句中完成。此用例不允许使用过程。 任何意见都受到高度赞赏。
最佳答案
使用窗口函数获取前 5 个:
select id, avg(reward)
from (select r.*,
row_number() over (partition by l.id order by r.date desc) as seqnum
from table1 l join
table2 r
on l.id = r.id and l.date > r.date
) r
where seqnum <= 5
group by id
having count(*) >= 5;
然后使用 having
子句来过滤掉那些没有五行的 id。
关于sql - 如何创建最多包含 5 个时间相关成员的每个分区的平均值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58922067/