我正在寻找最有效的方法来确定给定数据集中条纹的最长出现次数;特别是,确定最长的连胜纪录。
下面是我到目前为止的SQL,它似乎表现得非常快,并且正如我在大约100,000条记录的数据集上进行的有限测试所预期的那样。
DECLARE @HistoryDateTimeLimit datetime = '3/15/2018';
CTE从投票数据集创建结果子集。
WITH Results AS (
SELECT
EntityPlayerId,
(CASE
WHEN VoteTeamA = 1 AND ParticipantAScore > ParticipantBScore THEN 'W'
WHEN VoteTeamA = 0 AND ParticipantBScore > ParticipantAScore THEN 'W'
ELSE 'L'
END) AS WinLoss,
match.ScheduledStartDateTime
FROM
[dbo].[MatchVote] vote
INNER JOIN [dbo].[MatchMetaData] match ON vote.MatchId = match.MatchId
WHERE
IsComplete = 1
AND ScheduledStartDateTime >= @HistoryDateTimeLimit
)
CTE使用条件类型WinLoss
创建数据子集,并使用ROW_NUMBER()
创建分区中的总投票数。
WITH Streaks AS (
SELECT
EntityPlayerId,
ScheduledStartDateTime,
WinLoss,
ROW_NUMBER() OVER (PARTITION BY EntityPlayerId ORDER BY ScheduledStartDateTime) -
ROW_NUMBER() OVER (PARTITION BY EntityPlayerId, WinLoss ORDER BY ScheduledStartDateTime) AS Streak
FROM
Results
)
CTE总结WinLoss
分区投票条纹和开始日期/时间,以及条纹中的总计数。
WITH StreakCounts AS (
SELECT
EntityPlayerId,
WinLoss,
MIN(ScheduledStartDateTime) StreakStart,
MAX(ScheduledStartDAteTime) StreakEnd,
COUNT(*) as Streak
FROM
Streaks
GROUP BY
EntityPlayerId, WinLoss, Streak
)
CTE选择由玩家分组的MAXIMUM
(获胜)WinLoss
的{{1}}(最长)投票连胜。
W
从WITH LongestWinStreak AS (
SELECT
EntityPlayerId,
MAX(Streak) AS LongestStreak
FROM
StreakCounts
WHERE
WinLoss = 'W'
GROUP BY
EntityPlayerId
)
CTE中选择有用的数据。
LongestWinStreak
这是代码的第3次迭代;起初我觉得我正在过度思考并使用带SELECT * FROM LongestWinStreak
函数的窗口来定义一个稍后用于分区的重置周期。
[UPDATE]: http://sqlfiddle.com/#!18/5b33a/1处的SQLFiddle示例 - 上面使用的两个表的示例数据如下所示。 数据旨在显示模式,可以根据您自己的测试/使用进行推断;
LAG
表数据。
MatchVote
EntityPlayerId IsExtMatch MatchId VoteTeamA VoteDateTime IsComplete
-------------------- ------------ -------------------- --------- ----------------------- ----------
158 1 152639 0 2018-03-20 23:25:28.910 1
158 1 156058 1 2018-03-13 23:36:57.517 1
表数据。
MatchMetaData