我有一个查询生成的表,只要玩家继续获胜,就会计算连胜。当他们的球员获得正分数时,连胜数上升为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 |
+--------+--------+-----------+
我对如何实现这一点有任何想法?提前谢谢!
答案 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
列时获得的内容,因为您可以从提供的数据中获得该列
答案 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
我没有测试过这个查询,所以可能存在一些语法错误。但是,这种方法应该有效。出于性能原因,您可能希望在表,条带和时间戳上有索引。