问题描述
我正在解决一个问题,我需要为游戏玩家获取下一个可用的类别。如果玩家已达到最终类别(下图中的射手),那么我将需要返回到表的开头并转到下一个可用的类别。
以下是类别列表:
以下是玩家列表以及他们上一个 Category_ID 是什么:
最后,下面是我将使用的数据
现在我需要使用数据表为每个玩家找到下一个 Category_ID。如果玩家已经到达最后一个 Category_ID(在本例中为 ID 4 和玩家 C),那么它会像 1 一样重置回到顶部,但是玩家 C 将选择类别 2,因为该玩家没有类别。
如何使用每个游戏玩家的数据表选择下一个可用的类别,同时记住在到达结束时重置回到顶部?
以下是问题的代码示例:
DECLARE @Category AS TABLE
(
Category_ID INT IDENTITY(1,1),Description VARCHAR(255)
)
INSERT INTO @Category
VALUES('Sports'),('Adventure'),('Action'),('Shooter')
DECLARE @Gamer AS TABLE
(
Username VARCHAR(255),Last_Category_ID INT
)
INSERT INTO @Gamer
VALUES('Gamer A',('Gamer B',2),('Gamer C',4),('Gamer D',3)
DECLARE @Data AS TABLE
(
Username VARCHAR(255),Play_At DATETIME,Category_ID INT
)
INSERT INTO @Data
VALUES('Gamer A',GETDATE() -1,('Gamer A',3),2)
SELECT * FROM @Category
SELECT * FROM @Gamer
SELECT * FROM @Data
解决方法
如果我理解正确,您需要每个玩家的下一个未使用的类别 ID。然后在一切都完成后重新开始。
这是一种方法:
- 对于每个玩家,获取最大的当前类别。
- 对于每个类别,获取下一个类别。
- 同样获得第一个类别。
- 当没有下一个类别时,使用第一个。
这是使用横向连接的好机会:
select g.*,coalesce(cn.category_id,cf.category_id)
from @gamers g outer apply
(select max(category_id) as max_category_id
from @data d
where d.username = g.username
) c outer apply
(select top (1) cn.category_id
from @categories cn
where cn.categoryid > c.max_categoryid
) cn cross join
(select min(cf.category_id) as categoryi_d
from @categories cf
) cf;
Here 是一个 dbfiddle。
,我不是 100% 清楚您的 @Data
表是否代表起始类别,但这可能正是您所需要的,如果不是,请用示例数据的一些明确的预期结果进行说明。
使用 apply
来确定每个用户的起始类别(如果这确实是您的描述所需要的)和另一个以获得最大可能的类别,选择用户名,并使用 case expression
,对应的下一个类别名称或起始类别(如果它已经是最大类别)。
select
Username,( select description
from @category c
where c.category_Id=case when Last_Category_ID<m.Id then Last_Category_ID + 1 else startcat.Id end
) NextCategory
from @gamer g
outer apply (
select min(category_id) Id
from @data d
where d.username=g.Username
)startcat
outer apply (
select Max(category_Id) Id
from @category
)m