如何获取前 3 种类型中每组的值
How to get the values for every group of the top 3 types
我知道了 table ratings
:
id
user_id
类型
价值
0
0
休息
4
1
0
酒吧
3
2
0
电影
2
3
0
咖啡馆
1
4
1
休息
4
5
1
酒吧
3
6
1
电影
2
7
1
咖啡馆
5
8
2
休息
4
9
2
酒吧
3
10
3
电影
2
11
3
咖啡馆
5
我想要一个 table,每对 (user_id, type)
有一行,用于所有用户评分最高的 3 种类型(在整个 [=251= 中按 sum(value)
排名]).
想要的结果:
user_id
类型
价值
0
休息
4
0
咖啡馆
1
0
酒吧
3
1
休息
4
1
咖啡馆
5
1
酒吧
3
2
休息
4
3
咖啡馆
5
2
酒吧
3
我能够通过两个查询来做到这一点,一个查询获取前 3 个,另一个获取类型与前 3 个类型匹配的行。
有人知道如何将其放入单个查询中吗?
我想你只是想要 row_number()
。根据您的结果,您似乎需要每种类型三行,最高值:
select t.*
from (select t.*,
row_number() over (partition by type order by value desc) as seqnum
from t
) t
where seqnum <= 3;
您的描述表明您可能只需要每个用户都可以,这是一个小调整:
select t.*
from (select t.*,
row_number() over (partition by user order by value desc) as seqnum
from t
) t
where seqnum <= 3;
获取 3 个最高排名类型的每个用户的行,其中类型按其在整个 table.[=18= 中的价值总和排名]
所以这不完全是关于每个用户的前 3 种类型,而是关于总体上的前 3 种类型。并非所有用户都会有前 3 种类型的行,即使用户有 3 种或更多类型。
策略:
聚合以获得每种类型的总和值 (type_rnk
)。
只取前 3 名。(打破平局...)
加入主 table,消除任何其他类型。
按 user_id, type_rnk DESC
排序结果
SELECT r.user_id, r.type, r.value
FROM ratings r
JOIN (
SELECT type, sum(value) AS type_rnk
FROM ratings
GROUP BY 1
ORDER BY type_rnk DESC, type -- tiebreaker
LIMIT 3 -- strictly the top 3
) v USING (type)
ORDER BY user_id, type_rnk DESC;
db<>fiddle here
由于多个类型可以有相同的排名,我将 type
添加到排序顺序以按名称的字母顺序打破平局(因为您没有另外指定)。
事实证明,我们不需要 window functions - 带有 OVER
和可选 PARTITION
的那些。 (因为你在评论中问过)。
我知道了 table ratings
:
id | user_id | 类型 | 价值 |
---|---|---|---|
0 | 0 | 休息 | 4 |
1 | 0 | 酒吧 | 3 |
2 | 0 | 电影 | 2 |
3 | 0 | 咖啡馆 | 1 |
4 | 1 | 休息 | 4 |
5 | 1 | 酒吧 | 3 |
6 | 1 | 电影 | 2 |
7 | 1 | 咖啡馆 | 5 |
8 | 2 | 休息 | 4 |
9 | 2 | 酒吧 | 3 |
10 | 3 | 电影 | 2 |
11 | 3 | 咖啡馆 | 5 |
我想要一个 table,每对 (user_id, type)
有一行,用于所有用户评分最高的 3 种类型(在整个 [=251= 中按 sum(value)
排名]).
想要的结果:
user_id | 类型 | 价值 |
---|---|---|
0 | 休息 | 4 |
0 | 咖啡馆 | 1 |
0 | 酒吧 | 3 |
1 | 休息 | 4 |
1 | 咖啡馆 | 5 |
1 | 酒吧 | 3 |
2 | 休息 | 4 |
3 | 咖啡馆 | 5 |
2 | 酒吧 | 3 |
我能够通过两个查询来做到这一点,一个查询获取前 3 个,另一个获取类型与前 3 个类型匹配的行。
有人知道如何将其放入单个查询中吗?
我想你只是想要 row_number()
。根据您的结果,您似乎需要每种类型三行,最高值:
select t.*
from (select t.*,
row_number() over (partition by type order by value desc) as seqnum
from t
) t
where seqnum <= 3;
您的描述表明您可能只需要每个用户都可以,这是一个小调整:
select t.*
from (select t.*,
row_number() over (partition by user order by value desc) as seqnum
from t
) t
where seqnum <= 3;
获取 3 个最高排名类型的每个用户的行,其中类型按其在整个 table.[=18= 中的价值总和排名]
所以这不完全是关于每个用户的前 3 种类型,而是关于总体上的前 3 种类型。并非所有用户都会有前 3 种类型的行,即使用户有 3 种或更多类型。
策略:
聚合以获得每种类型的总和值 (type_rnk
)。
只取前 3 名。(打破平局...)
加入主 table,消除任何其他类型。
按 user_id, type_rnk DESC
SELECT r.user_id, r.type, r.value
FROM ratings r
JOIN (
SELECT type, sum(value) AS type_rnk
FROM ratings
GROUP BY 1
ORDER BY type_rnk DESC, type -- tiebreaker
LIMIT 3 -- strictly the top 3
) v USING (type)
ORDER BY user_id, type_rnk DESC;
db<>fiddle here
由于多个类型可以有相同的排名,我将 type
添加到排序顺序以按名称的字母顺序打破平局(因为您没有另外指定)。
事实证明,我们不需要 window functions - 带有 OVER
和可选 PARTITION
的那些。 (因为你在评论中问过)。