一个例子简单梳理下MySQL执行顺序

通过一个比较复杂的例子,展示MySQL的执行顺序。
先准备2张表,p表:id字段用于表示选手Id,主键。其次还有该选手所属赛区,国籍,和人气值。
r表:Id同p表,为选手Id,主键,还有一个字段为人气值的折扣率。比如,Clearlove在p表的人气值为5000,在r表的折扣率为0.9,那么真实人气值即为4500。
在这里插入图片描述
在这里插入图片描述


查询真实人气值大于本赛区本土选手的平均真实人气值的选手id和其对应的赛区,和真实人气值


这题的关键条件:“本赛区本土选手的平均真实人气值”,明显不是可以简单表示出来的,所以我们要做的,就是先查出这个“人气值”。
很明显,这个人气值是根据赛区分别计算的,所以会有2个,SQL如下:

SELECT
	AVG(p.point * R.rate) avg_point,
	division
FROM
	p
LEFT JOIN r ON p.id = R.id
WHERE
	p.division = 'LPL'
AND p.nation = 'China'
OR p.division = 'LCK'
AND p.nation = 'Korea'
GROUP BY
	division

现在,就来看一下这条语句的执行顺序。
①第一步自然就是from我们的p表。
②然后进行的步骤是表连接,和要连接的表先产生笛卡尔积,然后再根据连接条件(on)进行筛选。
③随后是where子句,他会在上表的基础上,把记录进行进一步的筛选。
④以上都还比较容易理解。随后就是group by 分组操作了,只要使用了该操作,查询的字段就要开始受限制了。
我们需要保证出现在select语句中的字段,一定是在聚合函数中,或者出现在了group by的后面。否则,语法上就是错误的(MySQL会执行查询,但结果往往不符合预期)。
如果细细想想group by的作用,上述的限制也就自然理解了。比如,我们想查询每个赛区的平均人气值,那么如果非要在select里,加上国籍nation字段,显然就失去了意义,完全没有办法进行对应。毕竟LPL里有中有韩,总不能一个字段有2个值吧。

再来看一个更加一般的情况:我们对下表的C2字段进行分组
在这里插入图片描述
很明显,我们现在在select中能选的,只有C2了。
在这里插入图片描述
或者,就是使用聚合函数,把多条字段变为一条,如C3,都是整数,那么不论是求最极值还是平均数,都是可以的。
在这里插入图片描述
而C1的话是字符串,就没有办法聚合了,一般也没有现实意义,所以基本不会有这种需求。这里也顺便体现了,聚合函数为什么叫聚合,就是因为它把多条数据进行了聚合,变为了一条。
⑤接下来的having子句,将对上表的记录,再进行一次筛选,并且是可以使用字段别名和聚合函数的,使用效果和where类似。
⑥剩下比较简单,就一起列举了:SELECT,SELECT子句中的表达式,DISTINCT,TOP,ORDER BY,LIMIT。

写好了子查询后,完整的SQL如下:

SELECT
	p.id,
	p.point * r.rate AS real_point,
	p.division
FROM
	p
INNER JOIN (
SELECT
	AVG(p.point * R.rate) avg_point,
	division
FROM
	p
LEFT JOIN r ON p.id = R.id
WHERE
	p.division = 'LPL'
AND p.nation = 'China'
OR p.division = 'LCK'
AND p.nation = 'Korea'
GROUP BY
	division
	HAVING
		avg_point > 2000
) c ON p.division = c.division
LEFT JOIN R ON p.id = R.id
WHERE
	p.point * R.rate >= c.avg_point
ORDER BY
	real_point DESC
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值