如何在PostgreSQL查询中显示行号?


72

我想显示一个PostgreSQL查询返回的每条记录的观察数。

我认为在8.4窗口功能可以执行此功能。


我认为我必须喜欢自己的问题,这样以后我才能
再说

30
+1这是我见过的第一个问题,完全由一个人提供的问题,答案和对话。
Xeoncross

2
:)至强,你只是让我发笑。我仍然不时地回到这个问题。
vol7ron 2011年

Answers:


105
select   row_number() over (order by <field> nulls last) as rownum, *
from     foo_tbl
order by <field>

如果不需要订购,则也可以简化此答案:

select row_number() over(), *  -- notice: no fields are needed
from   foo_tbl

SQL提琴概念证明


1
看来,如果这样做,over()它将始终递增地提供行号,例如1 2 3 4... 按照该特定结果的顺序(如果有外部查询会重新排列结果,则rownum可能会出现混乱,请参考:stackoverflow.com/a/4812038/32453,因此添加order by可能会在这种情况下非常有用(或者,如果你想不算空值,如在第一个例子)FWIW。
rogerdpack

1
这真的很酷-对于我们的新手,可以剖析一下它的工作原理吗?
zthomas.nc

2
@ zthomas.nc是一个窗口函数。想像一个熟悉的玻璃窗。如果需要,您可以将该窗口划分为较小的窗格(框架),所有结果仍然是唯一的,但跨框架划分。这种划分就是所谓的分区,即over()上述分区。如果您没有提供任何条件,则整个窗口只有一个窗格。Window functions之所以独特,是因为它们可以跨一帧的行而不是整个结果集进行计算。因此,如果您想row_number按性别来做,则可以使用over按性别进行划分。
vol7ron

似乎大大降低了大型查询的速度
cdyson37 '18

它不会产生太大影响。大型查询可能会遇到其他限制,例如减少工作内存。如果这是一个因素,那么行号和性能都是必需的,请考虑在表示层或后处理层中创建编号。
vol7ron

5

Postgres <8.4

对于8.4之前的版本:

SELECT    count(*) rownum, foo.*
FROM      datatable foo
JOIN      datatable bar
          ON (foo.pk_id <= bar.pk_id)
GROUP BY  foo.pk_id, foo.a, foo.b
ORDER BY  rownum
;

-- if there isn't a single unique/primary key field, you can concatenate fields
--    Example: ON (foo.a||foo.b||foo.c <= bar.a||bar.b||bar.c)

希望这对某人有帮助。

SQL提琴概念证明


另一种方法

我建议不惜一切代价避免这样做,但想将其包括在内。它有些昂贵,我想它不能很好地扩展,但是当表上不存在主键时(错误的db-design),您的选择可能会受到限制。在大多数情况下,建议在应用程序层执行编号。

-- Based on basic table w/o primary key
-- CREATE TABLE names ( name as text );

SELECT num, name[num]
FROM (
  select generate_series( 1, (select count(*) from names) ) as num
) _nums,
(
  select array_agg(name) as name from names
) _names

SQL提琴概念证明

无法扩展的原因:

  • 将元组打包成每行一个数组是一个坏主意

此方法应适用于任何符合SQL标准的数据库
vol7ron,2010年

我认为必须注意,null值应该与一致null。因此,coalesce()可能需要使用a。
vol7ron

2
窗口函数是SQL:2003标准的一部分。
a_horse_with_no_name 2012年

这将行不通,这不是排名行,请考虑10,6,6,2,行1,2,3,4,但与您的查询排名1,3,3,4。
亚瑟

@Arthur:什么是pk代表的主键。根据定义,PK除非是CK,否则必须是唯一的。另外,请阅读查询下方的评论;尽管在某些情况下它不起作用(例如,我不确定您是否可以串联空值)
vol7ron 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.