[英]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);
-- team with more goals wins and gets 3points -- team which lose gets 0points -- for a tie, each team gets 1point -进球数多的球队获胜并获得3分-输球的球队获得0分
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
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.