选择最后n行而不使用order by子句

时间:2011-10-31 06:43:29

标签: sql postgresql sql-order-by

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

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

2 个答案:

答案 0 :(得分:9)

你得到了你对Lukas解决方案的期望(截至2011年11月1日)纯粹的运气。根据定义,RDBMS中有 no“自然顺序”。您依赖于可能随新版本更改的实施细节,恕不另行通知。或者转储/恢复可以改变该顺序。当db统计信息发生更改并且查询计划程序选择导致不同行顺序的不同计划时,它甚至可以更改 out of the blue

获取“最后n”行的正确方法是使用时间戳或序列列,并使用ORDER BY该列。您可以想到的每个RDBMS都有ORDER BY,因此它就像'通用'一样。

quote the manual here

  

如果未给出ORDER BY,则按行的顺序返回行   系统发现生产速度最快。

Lukas的解决方案可以避免LIMIT,这在各种RDBMS中的实现方式不同(例如,SQL Server使用TOP n代替LIMIT),但需要ORDER BY,无论如何。

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

答案 1 :(得分:5)

使用窗口功能!

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将是您要获取的最后几行。当您对通用选择进行排序时,这也适用。

编辑:与我之前的例子相比有点不那么通用了:

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