87

有什么方法可以在 postgresql 中模拟 rownum 吗?

4

8 回答 8

97

PostgreSQL > 8.4

SELECT 
    row_number() OVER (ORDER BY col1) AS i, 
    e.col1, 
    e.col2, 
    ... 
FROM ... 
于 2010-10-18T13:41:12.033 回答
32

Postgresql 有限制。

甲骨文的代码:

select *
from
  tbl
where rownum <= 1000;

在 Postgresql 的代码中相同:

select *
from
  tbl
limit 1000
于 2015-09-25T12:28:05.837 回答
29

我刚刚在 Postgres 9.1 中测试了一个接近 Oracle ROWNUM 的解决方案:

select row_number() over() as id, t.*
from information_schema.tables t;
于 2012-10-03T09:50:47.870 回答
9

如果你只是想要一个号码回来试试这个。

create temp sequence temp_seq;
SELECT inline_v1.ROWNUM,inline_v1.c1
FROM
(
select nextval('temp_seq') as ROWNUM, c1 
from sometable
)inline_v1;

您可以将 order by 添加到 inline_v1 SQL,以便您的 ROWNUM 对您的数据具有一定的顺序意义。

select nextval('temp_seq') as ROWNUM, c1 
from sometable
ORDER BY c1 desc;

可能不是最快的,但如果您确实需要它们,这是一个选择。

于 2010-10-18T15:06:54.753 回答
4

如果您有唯一的密钥,您可以使用COUNT(*) OVER ( ORDER BY unique_key ) as ROWNUM

SELECT t.*, count(*) OVER (ORDER BY k ) ROWNUM 
FROM yourtable t;

| k |     n | rownum |
|---|-------|--------|
| a | TEST1 |      1 |
| b | TEST2 |      2 |
| c | TEST2 |      3 |
| d | TEST4 |      4 |

演示

于 2018-02-10T13:30:27.417 回答
2

Postgresql 没有相当于 Oracle 的 ROWNUM。在许多情况下,您可以通过在查询中使用 LIMIT 和 OFFSET 来获得相同的结果。

于 2010-10-18T13:41:05.180 回答
1

我认为可以使用临时序列来模仿 Oracle rownum。

create or replace function rownum_seq() returns text as $$
select concat('seq_rownum_',replace(uuid_generate_v4()::text,'-','_'));
$$ language sql immutable;

create or replace function rownum(r record, v_seq_name text default rownum_seq()) returns bigint as $$
declare 
begin
    return nextval(v_seq_name);
exception when undefined_table then
    execute concat('create temporary sequence ',v_seq_name,' minvalue 1 increment by 1');
    return nextval(v_seq_name);
end;
$$ language plpgsql volatile;

演示:

select ccy_code,rownum(a.*) from (select ccy_code from currency order by ccy_code desc) a where rownum(a.*)<10;

给出:

ZWD 1
ZMK 2
ZBH 3
ZAR 4
YUN 5
YER 6
XXX 7
XPT 8
XPF 9

说明:

函数rownum_seq()是不可变的,PG在一次查询中只调用一次,所以我们得到相同的唯一序列名(即使函数在同一个查询中被调用千次)

函数 rownum() 是 volatile 并且每次都由 PG 调用(即使在 where 子句中)

如果没有 r 记录参数(未使用),函数 rownum() 可能被过早地评估。这就是棘手的地方。想象一下,下面的 rownum() 函数:

create or replace function rownum(v_seq_name text default rownum_seq()) returns bigint as $$
declare 
begin
    return nextval(v_seq_name);
exception when undefined_table then
    execute concat('create temporary sequence ',v_seq_name,' minvalue 1 increment by 1');
    return nextval(v_seq_name);
end;
$$ language plpgsql volatile;


explain select ccy_code,rownum() from (select ccy_code from currency order by ccy_code desc) a where rownum()<10

Sort  (cost=56.41..56.57 rows=65 width=4)
  Sort Key: currency.ccy_code DESC
  ->  Seq Scan on currency  (cost=0.00..54.45 rows=65 width=4)
        Filter: (rownum('649aec1a-d512-4af0-87d8-23e8d8a9d982'::text) < 10)

PG 在订单前应用过滤器。该死!使用第一个未使用的参数,我们强制 PG 在过滤器之前排序:

explain select * from (select ccy_code from currency order by ccy_code desc) a where rownum(a.*)<10;

Subquery Scan on a  (cost=12.42..64.36 rows=65 width=4)
  Filter: (rownum(a.*, 'seq_rownum_43b5c67f_dd64_4191_b29c_372061c848d6'::text) < 10)
  ->  Sort  (cost=12.42..12.91 rows=196 width=4)
        Sort Key: currency.ccy_code DESC
        ->  Seq Scan on currency  (cost=0.00..4.96 rows=196 width=4)

优点:

  • 用作表达式或在 where 子句中
  • 易于使用:只需传递第一条记录。*您在 from

缺点:

  • 为遇到的每个 rownum() 创建一个临时序列,但在会话结束时将其删除。
  • 性能(讨论,row_number() over () 与 nextval)
于 2021-12-16T17:31:12.817 回答
0

使用限制子句,使用偏移量选择行号 -1 所以如果你想获得第 8 行,那么使用:

限制 1 偏移量 7

于 2017-04-22T06:59:38.777 回答