【问题标题】:SQL: Minimal break to next game per teamSQL:每支球队下一场比赛的最小休息时间
【发布时间】:2018-09-16 09:14:43
【问题描述】:

您好,这有点棘手,我正在努力奋斗。这超出了我正常的 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

我感觉我接近预期的结果,但最后一步不见了 -.-

【问题讨论】:

  • 我以为他是在寻求帮助以引导他走向正确的方向,稍加编辑就会更好地理解。但你是对的,我应该跳过,因为我不能 100% 确定这个决定。
  • 需要编辑意味着任何人都可以通过改进格式或修复小问题来解决问题。但是当 OP 自己必须添加信息时(比如他自己的努力,这里完全没有),那么它不是 EDIT,而是 CLOSE。除此之外:我很欣赏快速而善良的回归。你是对的:如有疑问,请跳过。老实说,对于绝大多数人来说,它应该是某种形式的 CLOSE。

标签: sql database ms-access ms-access-2016


【解决方案1】:

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

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

然后,您需要带入上一个游戏时间,计算日期时间差,然后汇总。

您可以使用相关子查询来获取之前的日期/时间:

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;

【讨论】:

  • 我将您的答案分成 6 个查询(1. 主队,2. 客队,3. 联合,4. 添加上一场比赛,5. 计算差异,6. 取最小值)但在结束它的工作。非常感谢:-)
【解决方案2】:

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

  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 上那样工作;你可能需要重新审视它。

【讨论】:

    【解决方案3】:

    它不会在大数据上表现出色,但它应该可以工作:

    先与主客队合并,然后加入后面的比赛,最后得到最小的差异:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-19
      相关资源
      最近更新 更多