【问题标题】:How to show row numbers in PostgreSQL query?如何在 PostgreSQL 查询中显示行号?
【发布时间】:2011-03-24 18:02:05
【问题描述】:

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

我认为 8.4 中的窗口函数可以执行此功能。

【问题讨论】:

  • 我想我必须收藏我自己的问题,这样我以后才能回到这个问题:)
  • +1 这是我看到的第一个完全由一个人提出的问题、答案和对话组成的问题。
  • :) Xeon,你让我笑了。我仍然每隔一段时间就会回到这个问题。

标签: sql database postgresql


【解决方案1】:
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 Fiddle 概念证明

【讨论】:

  • 看来,如果你这样做over(),那么它总是递增地给出行号,比如1 2 3 4... 按该特定结果的顺序(如果有重新排列结果的外部查询, 那么 rownum 可能会乱序 ref: stackoverflow.com/a/4812038/32453,因此在这些情况下添加 order by 可能很有用(或者如果您不想计算空值,如第一个示例所示)。FWIW。
  • 这真的很酷——对于我们这些新手来说,有人可以剖析它是如何工作的吗?
  • @zthomas.nc 它是一个窗口函数。想想熟悉的玻璃窗。如果您愿意,您可以将该窗口划分为更小的窗格(框架),所有结果仍然是唯一的,但跨框架划分。这种划分就是所谓的分区,这就是上面的over() 所做的。如果您没有提供任何条件,则整个窗口都会有一个窗格。 Window functions 的独特之处在于它们可以跨帧的行进行计算,而不是整个结果集。所以如果你想按性别做row_number,你可以用你的over来按性别分区。
  • 似乎大大减慢了大型查询
  • 它不应该有那么大的影响。也许您在使用大型查询时遇到了其他限制,例如工作内存减少。如果是这样一个因素,并且行数和性能都是必要的,请考虑在您的演示或后处理层中创建数字。
【解决方案2】:

Postgres

对于 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 Fiddle 概念证明


另一种方法

我建议不惜一切代价避免这种情况,但希望将其包括在内以供后代使用。它有点贵,我想不能很好地扩展,但是当表上不存在主键时(糟糕的数据库设计),您的选择可能会受到限制。在大多数情况下,建议在应用层执行编号。

-- 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 Fiddle 概念证明

无法扩展的原因:

  • 将元组打包到一个数组中的每一行是个坏主意

【讨论】:

  • 此方法适用于任何符合 SQL 标准的数据库
  • 我认为重要的是要注意null 值应该连接到null。因此,可能需要使用coalesce()
  • 窗口函数是 SQL:2003 标准的一部分。
  • 这行不通,这是排名而不是行,考虑 10,6,6,2 ,行 1,2,3,4,但您的查询排名 1,3,3,4。
  • @Arthur:你的主键是什么,这就是 pk 的意思。根据定义,PK 必须是唯一的,除非它是 CK。另外,请阅读查询下方的评论;尽管在某些情况下它不起作用(例如,我不确定您是否可以连接空值)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-18
  • 2018-05-31
  • 1970-01-01
  • 2011-08-28
  • 2021-06-14
  • 1970-01-01
相关资源
最近更新 更多