2013-03-24 69 views
3

如果你能帮我解决我的问题,那将会很酷。我有一张桌子,你可以从游戏中看到事件。每个玩家都有一定数量的黄金,你可以在Log in之后的Value列中看到。我需要找出在Log in之后有多少黄金玩家开始了他们的FIRST游戏。之前玩家开始游戏,他们可以Buy goldGet bonus将由Value开始触发器和结束触发器之间的GROUP行

**Player ID  Timestamp  Action  Value**  
    1111   09:11  Log in  500 
    1111   09:25  Buy gold 100 
    1111   09:28  Get bonus 50 
    1111   09:30  Start game  
    2222   11:14  Log in  800 
    3333   12:01  Log in  700 
    3333   12:04  Get bonus 50 
    3333   12:08  Start game 
    3333   12:15  Buy gold 100 
    3333   12:18  Start game 
    1111   14:40  Log in  300 
    1111   14:42  Buy gold 100 
    1111   14:50  Start game 
    2222   15:22  Log in  600 
    2222   15:25  Buy gold 100 
    2222   16:25  Log in  400 
    2222   16:30  Get bonus 50 
    2222   16:35  Start game  

特结果我要寻找提高他们的黄金量是类似的东西。它基本上是玩家的Start game和最近的Log in之间的值的总和。

**Match number Player ID  Value** 
    1    1111   650 
    2    3333   750 
    3    1111   400 
    4    2222   450 

谢谢!

+0

是匹配号码在你的基础表中的字段? – 2013-03-24 13:12:53

+0

@Gorionovic ..。你在这两段中说了两件不同的事。第一段说“我需要找出有多少黄金玩家在登录后开始玩FIRST游戏”。第二个说“这基本上是开始游戏和最近登录玩家之间的价值总和”。我认为示例数据与第一个定义更加一致,但是您能否解决问题以澄清您的意思? – 2013-03-24 14:09:37

+0

什么版本的SQL Server?请添加相应的标签。 – 2013-03-24 14:23:05

回答

1

一种方法是搜索每个Log in行。然后查找下一行,即Log inStart game。如果该行是Start game,则表示登录后可以识别第一个游戏。然后,您可以找到值的总和为对之间的所有行:

select row_number() over (order by start.Timestamp) as MatchNumber 
,  start.[Player ID] 
,  vals.SumValue 
from YourTable login 
cross apply 
     (
     select top 1 * 
     from YourTable start 
     where login.[Player ID] = start.[Player ID] 
       and login.Timestamp < start.Timestamp 
       and start.Action in ('Start game', 'Log in') 
     order by 
       start.Timestamp 
     ) start 
cross apply 
     (
     select sum(cast(vals.Value as int)) as SumValue 
     from YourTable vals 
     where vals.[Player ID] = start.[Player ID] 
       and vals.Action in ('Log in', 'Get bonus', 'Buy gold') 
       and vals.Timestamp between login.Timestamp and start.Timestamp 
     ) vals 
where login.Action = 'Log in' 
     and start.Action = 'Start game' 

Example at SQL Fiddle.

+0

非常有用!谢谢! – Gorionovic 2013-03-24 14:53:33

1

你可以尝试一些相关子查询:

SELECT PlayerID, SUM(value) FROM table a 
WHERE 
TimeStamp >= (SELECT MAX(TimeStamp) FROM table WHERE a.PlayerID = PlayerID AND Action = 'Log in') 
GROUP BY PlayerID 
+1

示例数据清楚地显示了1111的两行,所以通过PlayerId进行分组似乎不是正确的解决方案。 – 2013-03-24 14:10:29

0

这是一个有点复杂。我的做法是为每次登录找到下一个时间戳,即“登录”或“开始游戏”,然后返回到原始表以查找所有金条目。

select tli.playerId, tli.TimeStamp, sum(value) 
from (select t.*, 
      (select top 1 timestamp 
       from t t2 
       where t2.playerId = t.playerId and 
        t2.timestamp > t.timestamp and 
        t2.action in ('log in', 'start game') 
       order by timestamp 
      ) as nextTimestamp 
     from t 
     where t.action in ('log in') 
    ) tli join 
    t 
    on t.playerId = tli.playerId and 
     t.timestamp >= tli.timestamp and 
     t.timestamp < tli.nextTimeStamp 
group by tli.playerId, tli.timeStamp 
+0

带有'top'的子查询需要一个'order by'。对于两次登录后再进行一次开始游戏,这也会超过它的总和。 – Andomar 2013-03-24 13:26:24

+0

@Andomar。 。 。固定。 – 2013-03-24 13:27:49

+0

仍然总结了超过它应该在[sql小提琴](http://sqlfiddle.com/#!6/28d55/2/0) – Andomar 2013-03-24 13:32:18