做者:Julia Evans 译者:无明
连接:infoq.cn/article/Oke8hgilga3PTZ3gWvbg
不少 SQL 查询都是以 SELECT 开始的。不过,最近我跟别人解释什么是窗口函数,我在网上搜索”是否能够对窗口函数返回的结果进行过滤“这个问题,得出的结论是”窗口函数必须在 WHERE 和 GROUP BY 以后,因此不能”。数据库
因而我又想到了另外一个问题:SQL 查询的执行顺序是怎样的?segmentfault
好像这个问题应该很好回答,毕竟本身已经写了上万个 SQL 查询了,有一些还很复杂。但事实是,我仍然很难确切地说出它的顺序是怎样的。app
因而我研究了一下,发现顺序大概是这样的。SELECT 并非最早执行的,而是在第五个。函数
这张图与 SQL 查询的语义有关,让你知道一个查询会返回什么,并回答了如下这些问题:性能
但数据库引擎并不必定严格按照这个顺序执行 SQL 查询,由于为了更快地执行查询,它们会作出一些优化,这些问题会在之后的文章中解释。优化
因此:spa
有不少 SQL 实现容许你使用这样的语法:3d
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY full_name
从这个语句来看,好像 GROUP BY 是在 SELECT 以后执行的,由于它引用了 SELECT 中的一个别名。但实际上不必定要这样,数据库引擎能够把查询重写成这样:code
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY CONCAT(first_name, ' ', last_name)
这样 GROUP BY 仍然先执行。blog
数据库引擎还会作一系列检查,确保 SELECT 和 GROUP BY 中的东西是有效的,因此会在生成执行计划以前对查询作一次总体检查。
在实际当中,数据库不必定会按照 JOIN、WHERE、GROUP BY 的顺序来执行查询,由于它们会进行一系列优化,把执行顺序打乱,从而让查询执行得更快,只要不改变查询结果。
这个查询说明了为何须要以不一样的顺序执行查询:
SELECT * FROM owners LEFT JOIN cats ON owners.id = cats.owner WHERE cats.name = 'mr darcy'
若是只须要找出名字叫“mr darcy”的猫,那就不必对两张表的全部数据执行左链接,在链接以前先进行过滤,这样查询会快得多,并且对于这个查询来讲,先执行过滤并不会改变查询结果。
数据库引擎还会作出其余不少优化,按照不一样的顺序执行查询,不过我并非这方面的专家,因此这里就很少说了。
LINQ(C#和 VB.NET 中的查询语法)是按照 FROM…WHERE…SELECT 的顺序来的。这里有一个 LINQ 查询例子:
var teenAgerStudent = from s in studentList where s.Age > 12 && s.Age < 20 select s;
pandas 中的查询也基本上是这样的,不过你不必定要按照这个顺序。我一般会像下面这样写 pandas 代码:
df = thing1.join(thing2) # JOIN df = df[df.created_at > 1000] # WHERE df = df.groupby('something', num_yes = ('yes', 'sum')) # GROUP BY df = df[df.num_yes > 2] # HAVING, 对 GROUP BY 结果进行过滤 df = df[['num_yes', 'something1', 'something']] # SELECT, 选择要显示的列 df.sort_values('sometthing', ascending=True)[:30] # ORDER BY 和 LIMIT df[:30]
这样写并非由于 pandas 规定了这些规则,而是按照 JOIN/WHERE/GROUP BY/HAVING 这样的顺序来写代码会更有意义些。不过我常常会先写 WHERE 来改进性能,并且我想大多数数据库引擎也会这么作。
若有错误或其它问题,欢迎小伙伴留言评论、指正。若有帮助,欢迎点赞+转发分享。
欢迎你们关注民工哥的公众号:民工哥技术之路