许多SQL查询以SELECT开头。但是,最近我向其他人解释了什么是窗口函数。在网上搜索“是否可以对窗口函数返回的结果进行过滤”,得到的结论是“窗口函数必须在WHERE和GROUPBY之后,所以不能”。于是又想到另一个问题:SQL查询的执行顺序是怎样的?看来这个问题应该很容易回答。毕竟我写过几万条SQL语句,有些还是很复杂的。但问题是,我还是很难说到底是什么顺序。SQL查询的执行顺序于是研究了一下,发现顺序大概是这样的。SELECT不是第一个执行,而是第五个执行。这张图回答了这些问题这张图是关于SQL查询的语义,让您知道查询将返回什么,并回答了这些问题:我可以在GRROUPBY之后使用WHERE吗?(不是,WHERE是在GROUPBY之后!)窗口函数返回的结果可以过滤吗?(不是,窗口函数在SELECT语句中,而SELECT在WHERE和GROUPBY之后)是否可以根据GROUPBY中的东西进行ORDERBY?(是的,ORDERBY基本都是最后执行的,所以ORDERBY什么都可以)LIMIT是什么时候执行的?(最后!)但是数据库引擎不一定严格按照这个顺序执行SQL查询,因为为了更快的执行查询,他们会做一些优化,这会在以后的文章中说明。所以:如果你想知道查询是否有效,或者查询将返回什么,你可以参考这张图;当涉及到查询性能或索引相关的东西时,这个图是不适用的。混合因素:列别名有许多SQL实现允许您使用如下语法:SELECTCONCAT(first_name,'',last_name)ASfull_name,count(*)FROMtableGROUPBYfull_name,因为它引用了SELECT中的别名。但实际上,大可不必如此。数据库引擎可以重写查询如下:SELECTCONCAT(first_name,'',last_name)ASfull_name,count(*)FROMtableGROUPBYCONCAT(first_name,'',last_name)这样GROUPBY仍然先执行。数据库引擎还进行一系列检查以确保SELECT和GROUPBY中的内容有效,因此它会在生成执行计划之前对查询进行全面检查。数据库可能不会按此顺序执行查询(优化)。实际中,数据库可能不会按照JOIN、WHERE、GROUPBY的顺序执行查询,因为它们会进行一系列的优化,打乱执行顺序,从而可以更快的执行查询,只要查询结果没有改变。此查询说明了为什么查询需要以不同的顺序执行:SELECT*FROMownersLEFTJOINcatsONowners.id=cats.ownerWHEREcats.name='mrdarcy'如果您只需要查找名为“mrdarcy”的猫,则无需比较将两张表的所有数据进行leftjoin,在join之前进行filter,这样查询会快很多,而且对于这个查询,先进行filtering不会改变查询结果。数据库引擎可以进行许多其他优化来以不同的顺序执行查询,但我不是这方面的专家,所以我不会在这里深入讨论。推荐:MySQL全面优化,速度如飞。LINQ查询以FROMLINQ(C#和VB.NET中的查询语法)开头,顺序为FROM...WHERE...SELECT。下面是一个LINQ查询示例:varteenAgerStudent=fromsinstudentListwheres.Age>12&&s.Age<20selects;pandas中的查询基本上是这样的,但你不必按照这个顺序。我通常这样写熊猫代码:df=thing1.join(thing2)#JOINdf=df[df.created_at>1000]#WHEREdf=df.groupby('something',num_yes=('yes','sum'))#GROUPBYdf=df[df.num_yes>2]#HAVING,过滤GROUPBY结果df=df[['num_yes','something1','something']]#SELECT,选择要显示的列df.sort_values('sometthing',ascending=True)[:30]#ORDERBY和LIMITdf[:30]的写法并不是因为pandas规定了这些规则,而是按照JOIN/WHERE/GROUPBY/HAVING的顺序写代码更有意义。但是我经常先写WHERE来提高性能,我认为大多数数据库引擎都是这样做的。R语言中的dplyr还允许开发人员使用不同的语法编写SQL查询,以查询Postgre、MySQL和SQLite。
