sql 查询顺序

/ 2021-07-12 / 57人浏览 / 0人评论

sql 查询顺序

sql查询不是select开始

显然很多SQL查询都是从SELECT开始(实际上这篇文章只是关于SELECT查询,而不是INSERTS或任何东西)。

但!昨天我在做一个窗口函数解释,我在谷歌上搜索“你能根据窗口函数的结果过滤吗?”你能过滤窗口函数的结果吗?

最后,我得出结论:“窗口函数必须按照发生的位置和组运行,所以您不能这样做”。但这让我想到了一个更大的问题-SQL查询实际运行的顺序是什么?.

这是我直觉地感觉到的(“我已经编写了至少10,000个SQL查询,其中有些非常复杂!我必须知道这一点!“)但我很难确切地说出这个命令是什么。

SQL查询按以下顺序进行

我查了一下命令,就在这里!(选择不是第一件事,而是第五件事!)这是在推特上).

(我真的想找到一种比“SQL查询按这个顺序发生/运行”更准确的措辞方式,但我还没有搞清楚) SQL查询按以下顺序进行

在非图像格式中,顺序是:

FROM/JOIN所有的ON条件 WHERE GROUP BY HAVING SELECT(包括窗口功能) ORDER BY LIMIT 这个图表可以帮助你回答问题 这个图表是关于语义学对于SQL查询--它允许您分析给定查询将返回的内容,并回答以下问题:

我能做什么WHERE从一个GROUP BY?(不!在分组之前发生在哪里!) 我可以根据窗口函数的结果进行过滤吗?(不!窗口函数发生在SELECT,在这两种情况下都会发生。WHERE和GROUP BY) 我能ORDER BY基于我在小组里做的事?(是的!ORDER BY基本上是最后一件事,你可以ORDER BY(基于任何事情!) 什么时候LIMIT发生了吗?(在最后!) 实际上,数据库引擎并不按此顺序运行查询。因为它们实现了一系列优化,以使查询运行得更快--稍后我们将在文章中讨论这个问题。

因此:

当您只想了解哪些查询是有效的,以及如何对给定查询的结果进行推理时,可以使用此关系图。 你不应该使用这个图表来解释查询性能或任何涉及索引的事情,这是一件更复杂的事情,变量更多

混淆因素:列别名

Twitter上有人指出,许多SQL实现允许您使用以下语法:

SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
FROM table
GROUP BY full_name

这个查询使它看与GROUP BY一样,即使GROUP BY是第一个,也会发生在SELECT之后,因为GROUPBY但是对于组By来说,实际上没有必要在SELECT之后运行才能工作--数据库引擎可以将查询重写为

SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
FROM table
GROUP BY CONCAT(first_name, ' ', last_name)

先管理这个小组。

您的数据库引擎也肯定会做一系列检查,以确保在SELECT和GROUPBY中放置的内容在它开始运行查询之前是有意义的,因此在它开始提出执行计划之前,它必须将整个查询作为一个整体来查看。

查询实际上并不按这个顺序运行(优化!)

实际上,数据库引擎并不是通过加入、过滤、然后分组来实际运行查询,因为它们实现了一系列优化,重新排序,以使查询运行得更快,只要重新排序不会改变查询的结果。

一个简单的例子说明了为什么需要以不同的顺序运行查询才能使它们更快,这就是在这个查询中:

SELECT * FROM
owners LEFT JOIN cats ON owners.id = cats.owner
WHERE cats.name = 'mr darcy'

如果您只需要查找3只名为“Darcy先生”的猫,那么做整个左边连接并匹配2张表中的所有行都是愚蠢的--首先对名为“Darcy先生”的猫进行一些筛选要快得多。在这种情况下,过滤首先不会改变查询的结果!

数据库引擎在实践中实现的许多其他优化可能会使它们以不同的顺序运行查询,但这是没有空间的,老实说,这不是我擅长的事情。

Linq使用FROM 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)      # like a JOIN
df = df[df.created_at > 1000] # like a WHERE
df = df.groupby('something', num_yes = ('yes', 'sum')) # like a GROUP BY
df = df[df.num_yes > 2]       # like a HAVING, filtering on the result of a GROUP BY
df = df[['num_yes', 'something1', 'something']] # pick the columns I want to display, like a SELECT
df.sort_values('sometthing', ascending=True)[:30] # ORDER BY and LIMIT
df[:30]

这并不是因为pandas 对如何编写代码强加了任何具体的规则。只是按照联接/WHERE/GROUPBY/HAVING顺序编写代码通常是有意义的。(我经常把WHERE首先要提高性能,我认为大多数数据库引擎也会在实践中做得第一。

dplyr在R中,您还可以使用不同的语法查询Postgres、MySQL和SQLite等SQL数据库,这也是一个更符合逻辑的顺序。

我很惊讶我不知道 我在博客上写这篇文章,是因为当我发现它的顺序时,我感到非常惊讶,以至于我以前从未见过它这样写下来--它基本上解释了我直观地知道的为什么有些查询是允许的,而另一些查询是不允许的。所以我想把它写下来,希望它能帮助其他人也理解如何编写SQL查询。

文章来源:https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/

全部评论