在SQL中循环最有效的方法?

时间:2013-07-12 19:32:42

标签: sql sql-server tsql

我有2个SQL Server表:

Players (
    PlayerID INT,
    Name VARCHAR(50),
    Money INT
)
Game (
    GameID INT,
    PlayerID INT
)

我需要制作一个查询,列出每场比赛最赚钱的玩家。最好的方法是什么?

我认为它应该是这种逻辑的东西:

foreach(games)
{
   playersInGame = GetPlayersInGame()   
   return playerWithMostMoney from playersInGame
}

但我在TSQL中非常糟糕。

2 个答案:

答案 0 :(得分:4)

使用SQL时,您希望使用joingroup by操作来完成使用其他语言循环的工作。 SQL比这些语言有很多优点,特别是因为优化器可以从各种实现逻辑的方法中进行选择。例如,SQL引擎可以利用多个处理器,这在过程语言中很难。

在您的情况下,逻辑有两个部分。首先是将桌子加在一起,这为您提供了所有玩家的金额。第二是找到最好的一个。为此,我将使用窗口函数max()来获取最大金额(我经常会使用row_number(),但我认为max()更容易解释) :

select g.gameid, p.playerid, p.money
from (select g.gameid, p.playerid, p.money,
             max(p.money) over (partition by g.gameid) as MaxMoneyPerGame
      from games g join
           players p
           on g.playerid = p.playerid
     ) gp
where gp.money = gp.maxmoney;

表达式max(p.money) over (partition by g.gameid)正在计算每个游戏的最大金额(基于partition by子句)。最后的where条款是选择金额与最高金额匹配的玩家。

请注意,如果两个玩家拥有相同的最大值,则会同时选择两个玩家。 row_number()是另一种选择,它总是只选择一个玩家,即使存在具有相同最大货币价值的重复玩家。

答案 1 :(得分:3)

与戈登的答案类似,但使用rank

select gameid, playerid, money
from (select g.gameid, p.playerid, p.money,
             rank() over (partition by g.gameid order by p.money desc) rn
      from games g 
      join players p on g.playerid = p.playerid
     ) sq
where rn=1