是否保证保留子查询中的顺序?

Posted

技术标签:

【中文标题】是否保证保留子查询中的顺序?【英文标题】:Is order in a subquery guaranteed to be preserved? 【发布时间】:2013-04-27 05:48:30 【问题描述】:

我特别想知道 PostgreSQL。给定以下人为的示例:

SELECT name FROM
  (SELECT name FROM people WHERE age >= 18 ORDER BY age DESC) p
LIMIT 10

外部查询返回的名称是否保证与内部查询的顺序一致?

【问题讨论】:

由于优化,可能会按顺序返回……但根据SQL标准,子查询的顺序不影响主查询。 【参考方案1】:

不,将 order by 放在外部查询中:

SELECT name FROM
  (SELECT name, age FROM people WHERE age >= 18) p
ORDER BY p.age DESC
LIMIT 10

内部(子)查询返回结果集。如果您将 order by 放在那里,则从内部(子)查询传递到外部查询的中间结果集保证按照您指定的方式排序,但在外部查询中没有 order by,结果通过处理该内部查询结果集生成的 -set 不保证以任何方式排序。

【讨论】:

什么鬼?!如果它拒绝这样做,为什么不直接抛出语法错误呢? 内部(子)查询返回一个结果集。如果您将订单放在那里,则从内部(子)查询传递到外部查询的中间结果集保证按照您指定的方式排序,但外部查询生成的结果集通过处理该内部查询结果集,不是。 有趣的细微之处。除非加入第二个结果集,否则我暗示不会更改有序结果集的顺序,但可以看到第二次猜测优化器可能很困难。 @Adamantish,实际上,(似乎我仍然不同意),我认为是我不清楚。但别担心,先生,祝你有美好的一天! @CharlesBretana 但是如果你想在做额外的过滤/加入/...之前有一个偏移量,你会想在子集中订购,然后过滤,然后你需要再次订购以保证要保留的内部顺序(由于偏移量而需要)?【参考方案2】:

对于简单的情况,@Charles query 是最有效的。

更一般地,您可以使用窗口函数row_number() 将您喜欢的任何订单带到主查询中,包括:

在子查询的SELECT 列表中按列排序,因此不可重现 peers 根据ORDER BY 标准任意排序。 Postgres 将在子查询 within 的窗口函数中重用相同的任意顺序。 (但不是例如来自random() 的真正随机顺序!) 如果您不想保留子查询中对等点的任意排序顺序,请改用rank()

这对于复杂查询或多个查询层通常也可能更好:

SELECT name
FROM  (
   SELECT name, row_number OVER (ORDER BY <same order by criteria>) AS rn
   FROM   people
   WHERE  age >= 18
   ORDER  BY <any order by criteria>
   ) p
ORDER  BY p.rn
LIMIT  10;

【讨论】:

【参考方案3】:

不保证它们的顺序相同,但是当您运行它时,您可能会看到它通常遵循顺序。

您应该在主查询中下订单

SELECT name FROM
(SELECT name FROM people WHERE age >= 18) p
ORDER BY p.age DESC LIMIT 10

【讨论】:

以上是关于是否保证保留子查询中的顺序?的主要内容,如果未能解决你的问题,请参考以下文章

如何保留 $in 查询的游标顺序? [复制]

Collection接口

MYSQL 选择子查询如果存在

多表查询,子查询,及查询语句中语句执行的先后顺序和特点

MySQL5.7-连接查询子查询关键字顺序存储引擎

SQL 子查询, 如何按照IN的顺序查询