简体   繁体   English

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

[英]MySQL query to do a SELF join and perform aggregation

I have a requirement to get the data from mysql db. 我需要从mysql db获取数据。 below is the DDL, DML ,sample output and query. 以下是DDL,DML,示例输出和查询。 I need help on optimizing the query, because I am sure the query I have wrote is very basic. 我需要优化查询的帮助,因为我确信我编写的查询非常基础。

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);

-- rules -规则

-- team with more goals wins and gets 3points -- team which lose gets 0points -- for a tie, each team gets 1point -进球数多的球队获胜并获得3分-输球的球队获得0分


expected output [order by goals and then by team_name 预期输出[按目标排序,然后按team_name排序

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

QUERY 查询

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

You should perform the sum, group by and order by only on the most external 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

I would go for radical simplification: 我将进行根本简化:

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;

If you want all teams -- even those who have played no matches -- then use left join . 如果您想让所有球队,甚至没有参加比赛的球队,都可以使用left join

Use better criteria instead of having to union two queries. 使用更好的条件,而不必union两个查询。 Forget the union all and do this: 忘记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

This should be a good starting point. 这应该是一个很好的起点。 (untested) (未试)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM