是否保证保留子查询中的顺序?
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
【讨论】:
以上是关于是否保证保留子查询中的顺序?的主要内容,如果未能解决你的问题,请参考以下文章