您好,这很棘手,我很难挣扎。这超出了我的正常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队在16.09.2018的最短休息时间为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 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;
一种选择是在团队和游戏日使用内部联接的查询,然后使用以下内容计算每个检索记录的时间差:
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