MySQL 查询以执行 SELF 连接并执行聚合

MySQL query to do a SELF join and perform aggregation

我需要从 mysql 数据库获取数据。 下面是 DDL、DML、示例输出和查询。 我需要有关优化查询的帮助,因为我确定我编写的查询非常基础。

create table team (
team_id int,
team_name char(10)
);

create table matches (
matches_id int,
host_team_id int,
guest_team_id int,
host_goals int,
guest_goals int
);


insert into team values (10, 'mumbai');
insert into team values (20, 'delhi');
insert into team values (30, 'banglore');
insert into team values (40, 'chennai');
insert into team values (50, 'gujarat');
insert into matches values (1, 50, 20, 2,1); 
insert into matches values (2, 30, 40, 2,0); 
insert into matches values (3, 10, 50, 1,1); 
insert into matches values (4, 20, 30, 0,1); 
insert into matches values (5, 40, 20, 3,2); 
insert into matches values (6, 50, 30, 1,0); 
insert into matches values (7, 40, 10, 1,2);

--规则

-- 进球多的球队获胜并获得3分 -- 输的队伍得0分 -- 平局,每队得 1 分


预期输出[按目标排序然后按team_name

team_id |   team_name | goals
50          gujarat     7
30          bangalore   6
10          mumbai      4
40          chennai     3
20          delhi       0

查询

select * from (select team_id, team_name, sum(goals) as goals from (
select team_id, team_name,  
 SUM(  Case
  when host_goals > guest_goals then 3
  when host_goals = guest_goals then 1
  else  0
  end ) as goals
from team t , matches m1
where t.team_id = m1.host_team_id
group by team_id, team_name

union all

select team_id, team_name,  
 SUM(  Case
  when guest_goals  > host_goals then 3
  when host_goals = guest_goals then 1
  else  0
  end ) as goals
from team t , matches m1
where t.team_id = m1.guest_team_id
group by team_id, team_name
order by goals desc, team_name asc) as finalOut
group by team_id, team_name ) as t1
order by goals desc, team_name asc

您应该只对最外部的 select

执行求和、分组依据和排序依据
  select * from (select team_id, team_name, sum(goals) as goals from (
  select 
      team_id
    , team_name
    , Case
        when host_goals > guest_goals then 3
        when host_goals = guest_goals then 1
        else  0
      end  as goals
  from team t 
  Inner join matches m1 on  t.team_id = m1.host_team_id

  union all

  select 
      team_id
    , team_name
    , Case
        when guest_goals  > host_goals then 3
        when host_goals = guest_goals then 1
        else  0
      end  
  from team t 
  inner join matches m1 on t.team_id = m1.guest_team_id
  ) as finalOut
  group by team_id, team_name 
  order by goals desc, team_name asc

我会进行彻底的简化:

select t.team_id, t.team_name, sum(points) as points
from teams t join
     ((select host_team_id as team_id, host_goals as goals, 'host' as which,
              (case when host_goals > guest_goals then 3
                    when host_goals = guest_goals then 1
                    else 0
               end) as points
       from matches
      ) union all
      (select guest_team_id as team_id, guest_goals as goals, 'guest' as which
              (case when guest_goals > host_goals then 3
                    when guest_goals = host_goals then 1
                    else 0
               end) as points
       from matches
      )
     ) hg
     on hg.team_id = t.team_id
group by t.team_id, t.team_name
order by sum(points) desc, team_name;

如果您想要所有球队——甚至是那些没有参加过比赛的球队——然后使用 left join

使用更好的标准,而不必 union 两次查询。忘记 union all 并执行此操作:

select team_id, team_name,  
 SUM(
     (t.team_id = m1.host_team_id) * ((host_goals >= guest_goals) + 2 * (host_goals > guest_goals)) +
     (t.team_id = m1.guest__team_id) * ((host_goals <= guest_goals) + 2 * (host_goals < guest_goals)) 

 ) as goals
from team t , matches m1
where ((t.team_id = m1.host_team_id) or (t.team_id = m1.guest_team_id))
group by team_id, team_name

这应该是一个很好的起点。 (未经测试)