【问题标题】:Select last n rows without use of order by clause选择最后 n 行而不使用 order by 子句
【发布时间】:2011-10-31 06:43:29
【问题描述】:

我想从 Postgres 数据库中的表中获取最后 n 行。我不想使用ORDER BY 子句,因为我想要一个通用查询。有人有什么建议吗?

单个查询将不胜感激,因为我不想使用 Postgres 的 FETCH 光标。

【问题讨论】:

  • “不使用 order by”是逻辑上的废话。在没有ORDER BY 的查询中,顺序未定义并且没有“最后”行。您的意思可能是“不使用LIMIT”。
  • 嗨 Erwin,如果我不想使用 order by,这意味着我想要最后添加的 n 行。 Lukas 给出的解决方案给了我这个结果。数据库还维护插入行的顺序(据说是自然顺序),我想要最后 n 行。
  • 这是不可靠的。根据定义,RDBMS 中没有“自然顺序”。我要写的内容比评论要多,请看我的回答。
  • @mitalpritmani:欧文是对的。您不应该假设您将可靠地获得物理表中的最后 n 行。您可能至少要考虑按oid 甚至更好,按您自己的主键排序。那么,当然,整个问题已经过时了,你可以ORDER BY oid DESC LIMIT :n...
  • 附带说明,OID 列不再添加到用户表中(如果我是正确的,从 9.0 开始。)postgresql.org/docs/9.0/static/datatype-oid.html

标签: sql postgresql sql-order-by


【解决方案1】:

Lukas 的解决方案(截至 2011 年 11 月 1 日)如您所愿,那是纯属运气。根据定义,RDBMS 中没有“自然顺序”。您依赖的实施细节可能会随着新版本的变化而更改,恕不另行通知。或者转储/恢复可能会改变该顺序。当数据库统计信息发生变化并且查询规划器选择导致不同行顺序的不同计划时,它甚至可以突然改变

获取“最后 n”行的正确方法是有一个时间戳或序列列和 ORDER BY 该列。您能想到的每个 RDBMS 都有 ORDER BY,所以这是“通用”的。

quote the manual here:

如果没有给出 ORDER BY,则以任何顺序返回行 系统发现生产速度最快。

Lukas 的解决方案可以很好地避免 LIMIT,它在各种 RDBMS 中的实现方式不同(例如,SQL Server 使用 TOP n 而不是 LIMIT),但您需要 @ 987654328@无论如何。

值得一提的是,虽然窗口函数在 SQL 标准中,但它们仍然不像您希望的那样通用。例如,MySQL 不支持它们。

【讨论】:

  • 嘿欧文,感谢您的信息。我想我错过了这些要点。我阅读了手册并了解了您在此处引用的这一点。那么这是否意味着我不能从数据库中获得最后插入的行,而我总是必须使用 order by?请给我这些问题的答案。
  • @mitalpritmani:是的,不是这个意思。如果您希望“最后 n 行”可靠,您必须 ORDER BY(从而指定“最后”的确切含义)。其他一切都是纯粹的运气。如果您没有用于标识“最后”行的列,则必须添加 sequence 之类的内容。
【解决方案2】:

使用窗口函数!

select t2.* from (
  select t1.*, row_number() over() as r, count(*) over() as c
  from (
    -- your generic select here
  ) t1
) t2
where t2.r + :n > t2.c

在上面的示例中,t2.r 是每行的行号,t2.c 是您的通用选择中的总记录。 :n 将是您要获取的最后 n 行。当您对通用选择进行排序时,这也适用。

编辑:与我之前的示例相比没有那么通用:

select * from (
  select my_table.*, row_number() over() as r, count(*) over() as c
  from my_table
  -- optionally, you could sort your select here
  -- order by my_table.a, my_table.b
) t
where t.r + :n > t.c

【讨论】:

  • 嘿卢卡斯,你之前的回答很容易理解,我的意思是两个查询。您能否也将其作为示例,以便我接受您的回答?是的,这个查询应该以“select t2.* from(select t1.*, .....)”开头,所以请更正它。如果我先写 t1 然后写 t2,它会给我错误 - 缺少表“t2”的 FROM 子句条目。
  • @mitalpritmani:你说得对,我在那儿遇到语法错误...已更正,并恢复了我之前的示例
  • @LukasEder:这个答案具有误导性,因为它支持 OP 的迷信,他可以依靠没有ORDER BY 的自然秩序。请参阅我对此的回答。
  • @ErwinBrandstetter:好点。不过,我假设 OP 知道这一点。这就是为什么我说我的解决方案是通用的,它可以提供任何查询的最后 n 行,无论如何应用排序
  • 并且由于顺序未知,因此最后N条记录在语义上等价于前N条记录,或者任意N条记录.
猜你喜欢
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2014-07-17
  • 2016-01-25
相关资源
最近更新 更多