【问题标题】:what's the execution order of each part of a sql querysql查询各部分的执行顺序是什么
【发布时间】:2019-02-20 05:51:23
【问题描述】:

sql查询各部分的执行顺序是什么,如SELECT、DISTINCT、FROM、WHERE、GROUP BY、ORDER BY···

我搜索了很多网站说ORDER BY在SELECT之后执行,如果这是真的,像'select column1 from table1 order by column2'这样的简单查询不应该执行,因为执行SELECT之后,只有column1在数据集,它不能使用 column2 对数据集进行排序。但实际上它有效!

【问题讨论】:

  • 您对选择感到困惑,选择意味着从页面中选择所需的数据,而不是在某些控制台中显示所需的列。
  • 所以这意味着无论SELECT子句中列出了哪些列,mysql总是会搜索整个数据页?
  • OP 在他们的问题中声明“大量网站说 ORDER BY 在 SELECT 之后执行”这一事实向我表明,标记的副本不会包含他们寻求的答案,因为他们对 SELECT 子句执行 的含义意味着 更加困惑。他们已经发现ORDER BYSELECT 之后。

标签: mysql sql


【解决方案1】:

考虑一个查询 -

select distinct <columns> from 
table1 t1 inner join t2 
on t1.col=t2.col
where <conditions>
group by <col>
having <conditions>

执行顺序是 -

> From
> ON
> JOIN
> Where
> group by
> Having
> Select
> Distinct
> Order By

【讨论】:

  • 如果 'SELECT' 在 'ORDER BY' 之前执行,出现在 ORDER BY 子句中的列应该只是出现在 SELECT 列表中的列吗?
  • 为什么你认为第二个查询不起作用? selectorder by sqlfiddle.com/#!9/93d83b/1 之前完成
  • 我无法重新收集场景,我在使用 select 和 order by 时遇到问题,已从我的帖子中删除了这些更改
  • 问题是尝试在同一个 select 上使用别名。像这样:SELECT 2*field as new_alias, 3*new_alias 因为 SELECT 不是进程 new_alias 还不存在
  • 谢谢,很有帮助
【解决方案2】:

让我们分解两个针对两个表的查询,这两个表都包含两列。首先,我们做一个简单的:

SELECT t1.a,t2.d + 6 as e
FROM
    table1 t1
       inner join
    table2 t2
       on
           t1.a = t2.c
WHERE
    t1.b = 2
ORDER BY
    t2.c

让我们在完成每个子句时考虑什么是“范围内”:

  • FROM table1 t1 - 此时,我们有一个包含两列的结果集 - {t1.a, t1.b}

  • INNER JOIN table2 t2 ON ... - 我们现在有一个包含四列的结果集 - T1.a, t1.b, t2.c, t2.d}。我们个人也可能现在ac 相等,但这与分析无关。

  • WHERE - 尽管WHERE 可以从查询中过滤,但它不会更改构成结果集的列集 - 它仍然是{t1.a, t1.b, t2.c, t2.d}

  • SELECT - 我们没有GROUP BY 子句,因此SELECT 子句的工作是a) 标记一些列以供输出和b) 可能添加一些额外的列计算其值。这就是我们在这里所拥有的。我们最终得到一组{O(t1.a), t1.b, t2.c, t2.d, O(e = t2.d +6)}1

  • ORDER BY - 现在我们通过t2.c 订购,尽管它不会输出,但它仍在范围内

  • 最后,这个查询的输出被传递(技术上通过游标)并且只包含{a, e}。这些列不再有与之关联的“原始表”,非输出列消失在以太中。


SELECT
    t1.a,SUM(t2.d) as e
FROM
    table1 t1
       inner join
    table2 t2
       on
          t1.a = t2.c
GROUP BY t1.a
HAVING e > 5
ORDER BY t1.a
  • FROM/JOIN 子句与之前的相同,因此相同的分析占上风。同样,我们没有WHERE 子句,但它与列集无关。我们有{t1.a, t1.b, t2.c, t2.d}

  • SELECT/GROUP BY/DISTINCTDISTINCTGROUP BY 实际上是同一件事 - 两者都明确地标识一组列 (GROUP BY) 或通过它们存在于 SELECT 子句中。您不能将SELECTGROUP BY 解开,因为我们还必须计算聚合,并且聚合定义在SELECT 子句中。对于分组列中明显的每组不同的值,我们生成一个输出行,其中包含该组值以及任何计算的聚合。我们在这里生成{O(t1.a), O(e)}2that 是查询的其余部分可以观察到的结果集。原始结果集不在范围内。

  • HAVING - 我们可以只使用SELECT 子句3 生成的那些列。但同样,我们过滤,而不是列。

  • ORDER BY 也只能与SELECT 生成的列一起使用。

  • SELECT 完成时,无论如何我们只有输出列,但无论如何输出处理都是一样的。


希望,从上面你可以看到SELECT 可以以两种完全不同的方式工作;但至少现在您知道其中的区别以及由此产生的连锁反应。


1我在这里即时编造术语,但我使用 O() 包装器表示“此列将在最终结果集中”。

2这是您似乎一直期望 SELECT 始终表现出的行为,只为后面的子句提供“可输出”行。

3 包含对 SQL 标准的扩展,允许非分组和非聚合列显示为 HAVING 子句谓词。它们被有效地重写以用于 WHERE 子句。

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2011-01-16
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多