使用Sql查询在Football数据库中查找Comebacks

时间:2017-05-20 08:53:37

标签: sql sql-server database relational-database sql-server-2016

我有4张桌子。

匹配

 | id    | HomeTeamID  | AwayTeamID |
 --------|-------------|------------
 | 1     | 1           | 2
 | 2     | 1           | 3
 | 3     | 3           | 1

目标

 | id    | MatchID     | Minute    | TeamID
 --------|-------------|---------- |---------
 | 1     | 1           |     3     |   2
 | 2     | 1           |     5     |   1
 | 3     | 1           |     15    |   1
 | 4     | 2           |     43    |   3
 | 5     | 2           |     75    |   1
 | 6     | 2           |     85    |   1
 | 7     | 3           |     11    |   1
 | 8     | 3           |     13    |   3
 | 9     | 3           |     77    |   3

小组

 | id    | Name        | 
 --------|-------------|
 | 1     | Chelsea     | 
 | 2     | Arsenal     | 
 | 3     | Tottenham   |

管理员

 | id    | Name        | TeamID     |  
 --------|-------------|-------------
 | 1     | Conte       |    1
 | 2     | Wenger      |    2
 | 3     | Pochettino  |    3

我想获得经理们的复出比赛数量。例如,Conte的球队在比赛1和2中承认了第一个进球,但他们赢了。孔蒂有2次复出。 Pochettino在第3场比赛中有1次复出。我希望通过SQL Query找到它。

我找到了每支队伍的第一个比赛目标。但经过一些步骤后,我正在失去我正在做的事情。

SELECT MatchID, MIN(minute), g.TeamID
FROM Goals g
JOIN Managers m ON m.TeamID = g.TeamID
GROUP BY MatchID, g.TeamID

4 个答案:

答案 0 :(得分:1)

with cte 
(
MatchID,TeamID,TotalGoalTime,NoOfGoals,ManagerName,comeback)
as(SELECT MatchID, g.TeamID,sum(minutea) as'TotalGoalTime' ,count(*)as'NoOfGoals',m.name as'ManagerName'
,comeback =ROW_NUMBER() OVER(PARTITION BY MatchID order by sum(minutea) desc) 
FROM Goals g
JOIN Managers m ON m.TeamID = g.TeamID
join [Teams] t on t.Id=g.TeamId
GROUP BY MatchID, g.TeamID,m.name )
Select MatchID,TeamID,NoOfGoals,ManagerName from cte where comeback =1

上面的查询现在给我们整体回归,将更新回来的号码。

答案 1 :(得分:1)

如果你想计算足球比赛中的每一次复出,你可以使用下面的解决方案。然后回归的定义是每当一支球队在失去后更多地为对手得分一球。例如,对于以下场景,我们有三个回归:

Team A  Team B
  0    -   1     //team b scores
  1    -   1     //team a scores
  2    -   1     //team a scores (comeback for a)
  2    -   2     //team b scores 
  2    -   3     //team b scores (comeback for b)
  3    -   3     //team a scores
  4    -   3     //team a scores (comeback for a)

从上面看,似乎我们卷土重来,得分改变了,之前的得分是均匀的。我使用SUM OVERROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROWminute排序,以便在每次进球时计算得分。

以下是完整的工作示例:

DECLARE @matches TABLE
(   
    [id] TINYINT
   ,[HomeTeamID] TINYINT
   ,[AwayTeamID] TINYINT
);

DECLARE @Goals TABLE
(
    [id] TINYINT
   ,[MatchID] TINYINT
   ,[Minute] TINYINT
   ,[TeamID] TINYINT
);

DECLARE @Teams TABLE
(
    [id] TINYINT
   ,[Name] VARCHAR(12)
);

DECLARE @Managers TABLE
(
    [Id] TINYINT
   ,[Name] VARCHAR(12)
   ,[TeamID] TINYINT
);

INSERT INTO @matches ([id], [HomeTeamID], [AwayTeamID])
VALUES (1, 1, 2)
      ,(2, 1, 3)
      ,(3, 3, 1)
      ,(4, 1, 4);

INSERT INTO @Goals ([id], [MatchID], [Minute], [TeamID])
VALUES (1, 1, 3, 2)
      ,(2, 1, 5, 1)
      ,(3, 1, 15, 1)
      ,(4, 2, 43, 3)
      ,(5, 2, 75, 1)
      ,(6, 2, 85, 1)
      ,(7, 3, 11, 1)
      ,(8, 3, 13, 3)
      ,(9, 3, 77, 3)
      ,(10, 4, 3, 1)
      ,(11, 4, 5, 4)
      ,(12, 4, 10, 4)
      ,(13, 4, 12, 1)
      ,(14, 4, 25, 1)
      ,(15, 4, 46, 4)
      ,(16, 4, 60, 4)
      ,(17, 4, 72, 4)
      ,(18, 4, 84, 4);

INSERT INTO @Teams ([id], [Name])
VALUES (1, 'Chelsea')
      ,(2, 'Arsenal')
      ,(3, 'Tottenham')
      ,(4, 'Real Madrid');

INSERT INTO @Managers ([Id], [Name], [TeamID])
VALUES (1, 'Conte', 1)
      ,(2, 'Wenger', 2)
      ,(3, 'Pochettino', 3)
      ,(4, 'Zidane', 4);

WITH DataSource AS
(
    SELECT m.[id]
          ,m.[HomeTeamID]
          ,m.[AwayTeamID]
          ,ROW_NUMBER() OVER (PARTITION BY m.[id] ORDER BY g.[minute]) AS [EventID]
          ,IIF
           (
                SUM(IIF(m.[HomeTeamID] = g.[teamID], 1, 0)) OVER (PARTITION BY m.[id] ORDER BY g.[minute] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) - 1
                =
                SUM(IIF(m.[AwayTeamID] = g.[teamID], 1, 0)) OVER (PARTITION BY m.[id] ORDER BY g.[minute] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
                OR
                SUM(IIF(m.[HomeTeamID] = g.[teamID], 1, 0)) OVER (PARTITION BY m.[id] ORDER BY g.[minute] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
                =
                SUM(IIF(m.[AwayTeamID] = g.[teamID], 1, 0)) OVER (PARTITION BY m.[id] ORDER BY g.[minute] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) -1
               ,IIF(m.[HomeTeamID] = g.[teamID], 'H', 'A') -- (H)ome come back, (A)way come ba
              ,'N' -- no come back
           ) AS [ComeBack]
    FROM @matches m
    INNER JOIN @Goals g
        ON m.[id] = g.[MatchID]
)
SELECT T.[Name]
FROM DataSource DS
INNER JOIN @Teams T
    ON IIF([ComeBack] = 'H', [HomeTeamID], [AwayTeamID]) = T.[id]
WHERE DS.[EventID] <> 1
    AND DS.[ComeBack] <> 'N';

以上将给我们:

Chelsea
Chelsea
Chelsea
Tottenham
Real Madrid
Real Madrid

注意,我已经添加了一个匹配来证明这一点。

答案 2 :(得分:0)

我不会跟随足球比赛,但假设当球队承认第一个进球然后赢得比赛时,东山再起,我将使用以下逻辑来获得结果。

首先,我们需要在比赛中承认第一个进球的球队:

SELECT TeamID, MatchID FROM Goals WHERE GoalID in 
  (SELECT Min(GoalID) FROM Goals GROUP BY MatchID)

第二,对于每场比赛,我们需要在第一个进球的队伍中获胜的比赛。

SELECT MatchID FROM
(SELECT COUNT(GoalID) as TotalGoals, MatchID FROM Goals GROUP BY MatchID) AS MatchSummary
INNER JOIN 
(SELECT COUNT(GoalID) as TeamGoals, MatchID FROM 
  (SELECT TeamID, MatchID FROM Goals WHERE GoalID in 
      (SELECT Min(GoalID) FROM Goals GROUP BY MatchID)
  ) as GoalsOfTheTeamThatConcededFirstGoal 
GROUP BY MatchID) as SummaryOfTeamThatConcededFirstGoal
ON MatchSummary.MatchID = SummaryOfTeamThatConcededFirstGoal.MatchID 
WHERE (TotalGoals - TeamGoals) < TeamGoals

结合这两个查询,您将能够获得已经卷土重来的团队的TeamID。

我认为使用游标或临时表可以更好地完成此任务,但我希望尽可能简单地保持答案。因此我避免了它。你一定要探索这两种方法。

答案 3 :(得分:0)

在这里&#34;回归&#34;意味着球队承认了第一个进球,但球队赢了这场比赛。

我使用2个通用子查询,1)winners,其中包含来自每个游戏的MatchIDTeamID,而不是以抽奖结束。 2)first_goals,其中包含那些在比赛中获得第一个进球的TeamID&#39}。

因此,使用以下方法在这些子查询之间进行连接:

on winners.MatchID = first_goals.MatchID and winners.TeamID <> first_goals.TeamID

给了我们那些比赛,球队赢了,但没有得分第一球(即&#34;回归&#34;)。

最后,我们使用与TeamsManagers表的简单连接:

with Goals(id    , MatchID    , Minute   ,TeamID)   as (
    select 1     , 1           ,     3     ,   2 union all
    select  2     , 1           ,     5     ,   1 union all
    select  3     , 1           ,     15    ,   1 union all
    select 4     , 2           ,     43    ,   3 union all
    select  5     , 2           ,    75    ,   1 union all
    select 6     , 2           ,     85    ,   1 union all
    select  7     , 3           ,     11    ,   1 union all
    select  8     , 3           ,     13    ,   3 union all
    select 9     , 3           ,     77    ,   3 
),
Teams (id, Name) as(
    select 1     ,'Chelsea' union all
    select  2     ,'Arsenal' union all
    select  3     ,'Tottenham'  
),
Managers(id, Name, TeamID) as (
select  1    ,'Conte',    1 union all
select  2     ,'Wenger',   2 union all
select  3     ,'Pochettino',    3
 )

select winners.TeamID, winners.MatchID, Teams.Name, Managers.Name from  ( 
    select t1.* from 
    (
        select TeamID, MatchID, count(*) as goal_scored  from Goals
        group by TeamID, MatchID 
    )t1
    inner join 
    (
        select MatchID, max(goal_scored) as winner_goals_cnt from (
            select TeamID, MatchID, count(*) as goal_scored  from Goals
            group by TeamID, MatchID
        )t
        group by MatchID
        having min(goal_scored) <> max(goal_scored)
    )t2
    on t1.MatchID = t2.MatchID and t1.goal_scored = t2.winner_goals_cnt
) winners
inner join 
(
    select * from (
    select Goals.*, row_number() over(partition by MatchID order by  Minute, id) rn from Goals
    ) f
    where rn = 1
) first_goals
on winners.MatchID = first_goals.MatchID and winners.TeamID <> first_goals.TeamID
inner join Teams
on winners.TeamID = Teams.id
inner join Managers
on winners.TeamID = Managers.TeamID