【问题标题】:Execution order in SELECT statementSELECT 语句中的执行顺序
【发布时间】:2018-02-18 22:27:11
【问题描述】:

我正在阅读a documentation for postgreSQL SELECT statement,因为我想查找 SELECT 中的 SQL 语句的处理顺序。

在文档中它说:

SELECT 从零个或多个表中检索行。 SELECT的一般处理如下:(...)

  1. (...) SELECT DISTINCT ON 消除与所有指定表达式匹配的行。 (...)
  1. 如果指定了 ORDER BY 子句,则返回的行按指定的顺序排序。 (...)

它进一步说(DISTINCT clause description):

DISTINCT ON 表达式的解释规则与 ORDER BY(见上文)。请注意,每组的“第一行”是 不可预测,除非使用 ORDER BY 来确保所需的行 首先出现。 (...)

DISTINCT ON 表达式必须匹配最左边的 ORDER BY 表达式。 ORDER BY 子句通常包含额外的表达式,用于确定每个 DISTINCT ON 组中行的所需优先级。

我的自然期望是 ORDER BY 应该修改 DISTINCT ON 的结果,并且由于 DISTINCT ON 可能(并且可能会)给出不可预测的结果,所以它 - 简单地说 - 无用,如果没有在另一个 SELECT 查询之前。

SELECT语句中语句的实际执行顺序是什么?
特别是:为什么ORDER BY在DISTINCT ON之前处理?


我不是 postgreSQL 和 SQL 的经验丰富的用户,因此我不知道我是否在问正确的问题 (XY Problem)。如果您认为这个问题应该是“DISTINCT ON 究竟是如何工作的?”或者甚至可能是“关键字在 SELECT 语句中的位置重要吗?”或其他任何问题,请适当地编辑问题。

【问题讨论】:

    标签: sql postgresql select


    【解决方案1】:

    第一个“处理顺序”在 SQL 中有点误导。语句在执行前编译。实际执行可能看起来与 SQL 本身非常不同(实际上,执行表示为 DAG——有向无环图——看起来与 SELECT 语法完全不同)。

    DISTINCT ON 是 Postgres 扩展。它非常方便——让您在括号中的每个值都得到一行。而且,您可以控制哪一行。

    假设您有这样的数据:

    a    b    c
    A1   3    1
    A1   2    2
    A1   4    3
    A2   6    4
    A2   1    5
    

    当您想要指定每个值一个 行时,您使用distinct on。而且,它让你指定你想要的值。例如,要为每个a 获取具有最小值b 的行:

    select distinct on (a) a, b, c
    from t
    order by a, b asc;
    

    要获取每个a 的最高值为b 的行:

    select distinct on (a) a, b, c
    from t
    order by a, b desc;
    

    括号中的表达式需要与order by中的前导表达式匹配。

    您不会通过阅读文档来了解其工作原理。你需要使用它。

    此功能可以替换为带有row_number() 的子查询和外部查询中的where 子句。这可能是其他数据库没有采用类似功能的原因。

    【讨论】:

    • 我已经看到它在使用中。我现在花了几个小时寻找很多例子,我想我明白它是如何工作的。我只是不明白为什么 postgreSQL 会从 DISTINCT ON 到 ORDER BY 并使用它的结果表。如果它对这两个关键字起作用,那么一个人怎么知道它对其他关键字不起作用?在许多语言中,您可以使用括号来明确首先要做什么。在 SQL 的情况下,我很难理解每一步中当前的“结果”表是什么。
    • @AkaZecik:Postgres 首先根据order by对行进行排序,然后应用distinct on ()
    猜你喜欢
    • 2016-12-19
    • 1970-01-01
    • 2015-11-24
    • 2014-08-23
    • 2023-03-13
    • 2012-05-28
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多