当前用户ID位于中心的排行榜榜首-SQL查询
我有下表:当前用户ID位于中心的排行榜榜首-SQL查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有下表: +---------+------------+----------+-------+ | userId | campaignId | countryId| points| +---------+------------+----------+-------+ | 10 | 1 | 101 | 72 | | 3 | 1 | 101 | 30 | | 6 | 1
+---------+------------+----------+-------+
| userId | campaignId | countryId| points|
+---------+------------+----------+-------+
| 10 | 1 | 101 | 72 |
| 3 | 1 | 101 | 30 |
| 6 | 1 | 101 | 72 |
| 4 | 1 | 101 | 49 |
| 1 | 1 | 101 | 53 |
| 8 | 1 | 101 | 67 |
| 5 | 1 | 101 | 6 |
| 7 | 1 | 101 | 87 |
| 2 | 1 | 101 | 41 |
| 11 | 1 | 101 | 76 |
| 9 | 1 | 101 | 50 |
+---------+------------+----------+-------+
我已经创建了一个排行榜榜首列表,其查询如下:
select
RANK() OVER(order by T.points desc) AS rowRank,
T.UserID, T.points
from table as T
where T.campaignId=@campaignId
OFFSET (@page-1)*@limit ROWS FETCH NEXT @limit ROWS ONLY
上面的查询从上到下返回一个常规的toplist
但是,下一个要求是创建一个排行榜toplist,返回当前用户Id排名+上面的2个排名用户+下面的2个排名用户,总共5个用户应与当前用户一起列在中心
因此,其他输入参数应为:
set @userId = 8 // current user where leader board should center around
set @maxTopLimit = 2 // include 2 users ranked above current user
set @maxBottomLimit = 2 // include 2 users ranked below current user
返回的排行榜应该是这样的,中间有userId8
+---------+------------+----------+-------+---------|
| userId | campaignId | countryId| points| rowRank |
+---------+------------+----------+-------+---------+
| 11 | 1 | 101 | 76 | 3 |
| 10 | 1 | 101 | 72 | 4 |
#####|###### 8 | 1 #########|##### 101 |### 67 |## 5 ####|########
| 9 | 1 | 101 | 50 | 6 |
| 2 | 1 | 101 | 49 | 7 |
+---------+------------+----------+-------+------+--+
如何编写这样的SQL查询
的cte\u排名为(…)
来自cte\u排名cr,其中cr.UserId=@UserId
加入cr2.RowRank>=cr.RowRank-@before和cr2.RowRank上的cte_秩cr2
在子查询或公共表表达式中移动排名结果。
的cte\u排名为(…)
选择目标用户。
来自cte\u排名cr,其中cr.UserId=@UserId
将目标行与定义间隔内的所有行联接。
加入cr2.RowRank>=cr.RowRank-@before和cr2.RowRank上的cte_秩cr2
create table CampaignPoints
(
UserId int,
CampaignId int,
CountryId int,
Points int
);
insert into CampaignPoints (UserId, CampaignId, CountryId, Points) values
(10, 1, 101, 72),
( 3, 1, 101, 30),
( 6, 1, 101, 72),
( 4, 1, 101, 49),
( 1, 1, 101, 53),
( 8, 1, 101, 67),
( 5, 1, 101, 6),
( 7, 1, 101, 87),
( 2, 1, 101, 41),
(11, 1, 101, 76),
( 9, 1, 101, 50);
declare @userId int = 8;
declare @before int = 2;
declare @after int = 2;
with cte_rank as
(
select cp.UserId,
cp.CampaignId,
cp.CountryId,
cp.Points,
rank() over(order by cp.Points desc) as RowRank
from CampaignPoints cp
)
select cr2.*
from cte_rank cr
join cte_rank cr2
on cr2.RowRank >= cr.RowRank - @before
and cr2.RowRank <= cr.RowRank + @after
where cr.UserId = @userId
order by cr2.RowRank;
UserId CampaignId CountryId Points RowRank
------ ---------- --------- ------ -------
10 1 101 72 3
6 1 101 72 3
8 1 101 67 5
1 1 101 53 6
9 1 101 50 7