MYSQL查询连胜包括得分

时间:2012-12-04 10:48:37

标签: mysql

我有一个查询生成的表,只要玩家继续获胜,就会计算连胜。当他们的球员获得正分数时,连胜数上升为1,如果他获得负分数,连胜将回落到0.表格如下:

+--------+------------------+--------+--------+
| player |    timestamp     | points | streak |
+--------+------------------+--------+--------+
| John   | 22/11/2012 23:01 |     -2 |      0 |
| John   | 22/11/2012 23:02 |      3 |      1 |
| John   | 22/11/2012 23:04 |      5 |      2 |
| John   | 22/11/2012 23:05 |     -2 |      0 |
| John   | 22/11/2012 23:18 |     15 |      1 |
| John   | 23/11/2012 23:20 |      5 |      2 |
| Chris  | 27/11/2012 22:12 |     20 |      1 |
| Chris  | 27/11/2012 22:14 |    -12 |      0 |
| Chris  | 27/11/2012 22:17 |      4 |      1 |
| Chris  | 27/11/2012 22:18 |     -4 |      0 |
| Chris  | 27/11/2012 22:20 |     10 |      1 |
| Chris  | 27/11/2012 22:21 |     20 |      2 |
| Chris  | 27/11/2012 22:22 |     90 |      3 |
+--------+------------------+--------+--------+

我想让球员获得最大连胜,这很容易获得,但我还想包括球员在那条特殊连胜中得分。因此,对于上面的示例,结果必须如下所示:

+--------+--------+-----------+
| player | points | maxstreak |
+--------+--------+-----------+
| John   |     20 |         2 |
| Chris  |    120 |         3 |
+--------+--------+-----------+

我对如何实现这一点有任何想法?提前谢谢!

2 个答案:

答案 0 :(得分:1)

我没有机会实际尝试这个,但是应该使用mySQL变量...

一开始,最里面的查询只是从得分表中查询,并按照播放器和时间戳的顺序强制数据。从那以后,我必须按顺序处理MySQL变量。首先......在处理的每个新记录上,如果我在不同的“播放器”(实际上应该基于ID而不是名称),我将条纹,点,maxStreak,maxStreakPoints重置为零,那么将最后一个用户设置为即将处理的用户。

在那之后,我正在检查连胜状态,积分等......

一旦将所有表格制成表格,我就会使用OUTERMOST查询来获得每个玩家的最高连胜/最高连胜点数。

SELECT
      Final.Player,
      MAX( Final.MaxStreak ) MaxStreak,
      MAX( Final.MaxStreakPoints ) MaxStreakPoints 
   FROM 
      ( 
        SELECT 
              PreOrd.Player,
              PreOrd.TimeStamp,
              PreOrd.Points,
              @nStreak       := case when PreOrd.Points < 0 then 0
                                     when PreOrd.Player = @cLastPlayer then @nStreak +1
                                     else 1 end  Streak,                              

              @nStreakPoints := case when @nStreak = 1 then PreOrd.Points
                                     when @nStreak > 1 then @nStreakPoints + PreOrd.Points
                                     else 0 end  StreakPoints,

              @nMaxStreak    := case when PreOrd.Player != @cLastPlayer then @nStreak
                                     when @nStreak > @nMaxStreak then @nStreak
                                     else @nMaxStreak end MaxStreak,

              @nMaxStreakPoints := case when PreOrd.Player != @cLastPlayer then @nStreakPoints
                                        when @nStreak >= @nMaxStreak and @nStreakPoints > @nMaxStreakPoints then @nStreakPoints
                                        else @nMaxStreakPoints end MaxStreakPoints,

              @cLastPlayer := PreOrd.Player PlayerChange
         FROM 
              ( select
                      S.Player,
                      S.TimeStamp,
                      S.Points
                   from 
                      Scores2 S
                   ORDER BY 
                      S.Player,
                      S.TimeStamp,
                      S.`index` ) PreOrd,
              ( select
                      @nStreak := 0,
                      @nStreakPoints := 0,
                      @nMaxStreak := 0,
                      @nMaxStreakPoints := 0,
                      @cLastPlayer := '~' ) SQLVars
      ) as Final
   group by 
      Final.Player 

现在,这可能会给出一个虚假的最大连胜点数,这样一个人得分就可以得到90分,然后是1分为10分,2分为10分,3分为10分,总共30分。考虑到这一点虽然...... :)

这是我在添加index列时获得的内容,因为您可以从提供的数据中获得该列 enter image description here

SQL Fiddle Showing my solution...

答案 1 :(得分:0)

我的建议是在计算条纹时存储其他信息。例如,您可以在条纹开始时存储时间戳。

一个不太严肃的建议是切换到另一个支持窗口功能的数据库。这会容易得多。

方法是找到条纹何时开始,然后在该时间和最大条纹之间总结所有内容。为此,我们将使用相关子查询:

select t.*,
       (select max(timestamp) from t t2 where t2.timestamp <= t.timestamp and t2.player = t.player and t2.streak = 0
       ) as StreakStartTimeStamp
from t
where t.timeStamp = (select max(streak) from t t2 where t.player = t2.player)

现在,我们将此查询作为子查询嵌入,因此我们可以添加适当的时间:

select t.player,
       sum(s.points)
from t join
     (select t.*,
             (select max(timestamp) from t t2 where t2.timestamp <= t.timestamp and t2.player = t.player and t2.streak = 0
             ) as StreakStartTimeStamp
      from t
      where t.streak = (select max(streak) from t t2 where t.player = t2.player)
     ) s
     on t.player = s.player
group by t.player

我没有测试过这个查询,所以可能存在一些语法错误。但是,这种方法应该有效。出于性能原因,您可能希望在表,条带和时间戳上有索引。