在PostgreSQL中跳过每第n个结果行

whlutmcx  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(4)|浏览(172)

我正在寻找一种在PostgreSQL中跳过行的方法。
我可以使用两种方法来做到这一点:

SELECT * FROM table WHERE id % 5 = 0

但是,我必须获取连续的行才能正确地跳过。例如,如果我获取row(with ids)0,3,5,它不会跳过5行中的4行,而是导致(ids)0和5。
或者跳过SQL以外的部分:

$count = 0;
while($row = progres_fetch_row($result))
  if ($count++ % 5 == 0)
     // do something

从SQL数据库中获取每第n行的最快方法是什么?

ffscu2ro

ffscu2ro1#

如果你使用PostgreSQL,你可以使用row_number()

SELECT t.*
FROM (
  SELECT *, row_number() OVER(ORDER BY id ASC) AS row
  FROM yourtable
) t
WHERE t.row % 5 = 0
t1rydlwq

t1rydlwq2#

如果n足够大(比如1000),你可以考虑使用WITH RECURSIVE查询:

WITH RECURSIVE foo(name) AS
    (SELECT name FROM people ORDER BY name LIMIT 1)
  UNION
    (SELECT
      (SELECT name FROM people
        WHERE name >= foo.name
        ORDER BY name OFFSET 1500 LIMIT 1)
      FROM foo LIMIT 1
    )
SELECT * FROM foo
bvn4nwqk

bvn4nwqk3#

@Guillaume Poussel可以很好地跳过第n行,但是如果我们想删除0到x范围内的n个元素,它不会包括第0行。
所以,如果我们只想包含从0开始的每第5个元素,这是解决方案:

SELECT t.*
FROM (
  SELECT *, row_number() OVER() AS row
  FROM dcia.test
) t
WHERE (t.row-1) % 5 = 0

原始索引:

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

上述语句后的索引:

0,5,10,15
iovurdzv

iovurdzv4#

这里有一个通用的解决方案,可能会很慢,以防您无法访问排名函数,如row_number()。在MySQL中,你可以这样写:

select * 
from x x1
where (
  select count(*) 
  from x x2 
  where x2.id <= x1.id
) % 5 <> 0
order by x1.id asc

如果你想添加额外的 predicate ,只需要确保将它们添加到外部和内部查询中:

select * 
from x x1
where x1.id % 2 = 0
and (
  select count(*) 
  from x x2 
  where x1.id % 2 = 0
  and x2.id <= x1.id
) % 5 <> 0
order by x1.id asc
  • SQLFiddle 1
  • SQLFiddle 2

备注:

  • 内部查询必须具有与外部查询相同的表引用和 predicate
  • 内部查询需要计算外部查询中当前行“之前”的行数。“Before”由外部查询的ORDER BY子句定义

相关问题