SQL:每队下一场比赛的最少休息时间

SQL: Minimal break to next game per team

你好,这有点棘手,我正在努力奋斗。这超出了我正常的 SQL 技能 :-) 这是我面临的问题。

我有一个游戏计划。基本结构如下所示:

ID     League     GameDay     GameTime    HomeTeam     AwayTeam
1        1       16.09.2018    10:00         A            B
2        1       16.09.2018    10:00         C            D
3        1       16.09.2018    14:00         E            F
4        1       16.09.2018    14:00         A            C
5        1       16.09.2018    17:00         B            D
6        1       16.09.2018    17:00         F            A
7        1       17.09.2018    10:00         E            D
8        1       17.09.2018    10:00         C            B
----> This goes on till league 6

我现在需要查询每个团队每天的最短休息时间(还有每个联赛,但团队名称是唯一的)。因此,在上面的示例中,A 队在 2018 年 9 月 16 日的最短休息时间为 3 小时(17:00 的比赛减去 14:00 的比赛)。

经过几次尝试,我想我意识到我不能在一个查询中做到这一点,所以我将其分解为一个团队。并创建了一些具有以下结果的查询(我在查询中只选择了 HomeTeam,然后选择了 AwayTeam 并将这两个合并):

League      GameDay     GameTime       Team
  1        16.09.2018    10:00          A
  1        16.09.2018    14:00          A
  1        16.09.2018    17:00          A
  1        16.09.2018    10:00          A
  1        16.09.2018    10:00          B
  1        16.09.2018    17:00          B
  1        17.09.2018    10:00          B
---> And so on with the other teams

我感觉我接近想要的结果,但缺少最后一步 -.-

一种选择是在团队和比赛日使用带有内部联接的查询,然后计算每个检索到的记录的时间差:

  SELECT GP1.HOMETEAM AS TEAM, GP1.GAMEDAY AS GAMEDAY, 
         CASE WHEN GP1.GAMETIME>GP2.GAMETIME THEN TIMEDIFF(GP1.GAMETIME, GP2.GAMETIME) ELSE TIMEDIFF(GP2.GAMETIME, GP1.GAMETIME) END AS TIMEDIFF
  FROM GAMEPLAN GP1 
    INNER JOIN GAMEPLAN GP2 
      ON (GP1.HOMETEAM=GP2.HOMETEAM OR GP1.HOMETEAM=GP2.AWAYTEAM) 
          AND GP1.GAMEDAY=GP2.GAMEDAY 
          AND GP1.GAMETIME!=GP2.GAMETIME

这将为每个在场的主队生成一些记录(因为它将计算同一支球队在同一天进行的每场比赛的差异)。 此外 - 仅此一项,任何从未出现在主队列表中的球队都将从结果集中消失。 所以,需要一个联合来覆盖那些(类似于上面),然后查询只得到时间差最小的结果:

SELECT MIN(TIMEDIFF), TEAM, GAMEDAY FROM (
  SELECT GP1.HOMETEAM AS TEAM, GP1.GAMEDAY AS GAMEDAY, 
         CASE WHEN GP1.GAMETIME>GP2.GAMETIME THEN TIMEDIFF(GP1.GAMETIME, GP2.GAMETIME) ELSE TIMEDIFF(GP2.GAMETIME, GP1.GAMETIME) END AS TIMEDIFF
  FROM GAMEPLAN GP1 
    INNER JOIN GAMEPLAN GP2 
      ON (GP1.HOMETEAM=GP2.HOMETEAM OR GP1.HOMETEAM=GP2.AWAYTEAM) 
          AND GP1.GAMEDAY=GP2.GAMEDAY 
          AND GP1.GAMETIME!=GP2.GAMETIME
UNION
  SELECT GP1.AWAYTEAM AS TEAM, GP1.GAMEDAY AS DAY,
         CASE WHEN GP1.GAMETIME>GP2.GAMETIME THEN TIMEDIFF(GP1.GAMETIME, GP2.GAMETIME) ELSE TIMEDIFF(GP2.GAMETIME, GP1.GAMETIME) END AS TIMEDIFF
  FROM GAMEPLAN GP1 
    INNER JOIN GAMEPLAN GP2 
      ON (GP1.AWAYTEAM=GP2.HOMETEAM OR GP1.AWAYTEAM=GP2.AWAYTEAM) 
          AND GP1.GAMEDAY=GP2.GAMEDAY 
          AND GP1.GAMETIME!=GP2.GAMETIME) T
  GROUP BY TEAM, GAMEDAY;

请注意 - 我不完全确定 'timediff' 函数是否会像在 MS-ACCESS 上那样工作;您可能需要重新访问它。

它在大数据上表现不佳,但应该可以:

先与主客场并集,再与后面的比赛合并,最后得到最小差值:

select team, gameday, min(breaktime) from
  (select t.team, t.gameday, g.gametime - t.gametime as breaktime from 
    (select id, league, gameday, gametime, hometeam as team from gameplan
    union 
    select id, league, gameday, gametime, awayteam as team from gameplan) t 
    join gameplan g on t.team in (g.hometeam , g.awayteam) and t.gameday = g.gameday and t.gametime < g.gametime ) breaks
group by team, gameday

这是一个真正的痛苦。首先,您需要一个包含每个团队 一个 列的所有游戏的列表:

select id, league, hometeam as team, gameday, gametime
from gameplan
union all
select id, league, awayteam as team, gameday, gametime
from gameplan;

然后,你需要带入之前的游戏时间,计算时间差,并汇总。

你可以使用相关子查询来获取之前的date/time:

select gp.*,
       (select max(gp2.dametime)
        from gameplan as gp2
        where gp.gameday = gp2.gameday and
              gp.team in (gp2.hometeam, gp2.awayteam) and
              gp2.gametime < gp.gametime
       ) as prev_gametime
from (select id, league, hometeam as team, gameday, gametime
      from gameplan
      union all
      select id, league, awayteam as team, gameday, gametime
      from gameplan
     ) as gp;

最后,你要的是最小差值:

select league, team, gamedate,
       min(datediff("minute", prev_gametime, gametime)) as minimum_break_length
from (select gp.*,
             (select max(gp2.gametime)
              from gameplan as gp2
              where gp.gameday = gp2.gameday and
                    gp.team in (gp2.hometeam, gp2.awayteam) and
                    gp2.gametime < gp.gametime
             ) as prev_gametime
      from (select id, league, hometeam as team, gameday, gametime
            from gameplan
            union all
            select id, league, awayteam as team, gameday, gametime
            from gameplan
           ) as gp
      ) as gp
group by league, team, gamedate;