我有一个表,其中存储有关文件的基本信息:

CREATE TABLE filez (
    id     INTEGER NOT NULL,
    name   TEXT NOT NULL,
    size   BIGINT NOT NULL
);
CREATE UNIQUE INDEX filez__id__idx ON filez USING (id);

我需要 Select 一组组合大小不超过某个阈值的文件.下面是一个实现这一点的普通查询(它可以使用非materialized CTE语法,但这在本例中并不重要):

SELECT id, name
FROM (
        SELECT id, name,
            SUM(size) OVER w AS total_size -- accumulating size of files
        FROM filez
        WINDOW w AS (ORDER BY id ASC RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
        ORDER BY id ASC
    ) AS t
WHERE total_size <= THRESHOLD

我在这个查询中遇到了一个Personal😄问题:无论是否达到阈值,它都会判断所有记录.我希望查询只遍历足够数量的记录(按索引的"id"字段排序),并在阈值条件变为False时立即停止执行.

编辑.

也许停止查询的问题可以推广.如果有一个函数,让我们将其命名为stop_query(BOOL):BOOL,它可以根据任意条件提前结束查询执行,如下例所示:

SELECT f1, f2
FROM tab1
WHERE stop_query(<some condition>)

或者

SELECT f1, f2
FROM tab1
WHERE CASE WHEN <some condition> THEN stop_query() ELSE TRUE END

推荐答案

您可以使用以cursor为基础的function:demo

create function filez_up_to_limit(p_limit numeric, p_cutoff_id int default 0) 
  returns table(id int,name text,size bigint)
language plpgsql as $f$
declare rc cursor for select * from filez 
                      where filez.id>p_cutoff_id 
                      order by filez.id;
        current_size int:=0;
begin
 open rc;
 while current_size<p_limit loop
   fetch rc into id,name,size;
   return next;
   current_size:=current_size+size;
 end loop;
end $f$;
explain analyze verbose 
select * from filez_up_to_limit(1e6);
QUERY PLAN
Function Scan on public.filez_up_to_limit (cost=0.25..10.25 rows=1000 width=44) (actual time=6.680..6.791 rows=1978 loops=1)
  Output: id, name, size
  Function Call: filez_up_to_limit('1000000'::numeric, 0)
Planning Time: 0.037 ms
Execution Time: 6.961 ms
explain analyze verbose 
select * from filez_up_to_limit(1e7);
QUERY PLAN
Function Scan on public.filez_up_to_limit (cost=0.25..10.25 rows=1000 width=44) (actual time=38.977..40.305 rows=20111 loops=1)
  Output: id, name, size
  Function Call: filez_up_to_limit('10000000'::numeric, 0)
Planning Time: 0.020 ms
Execution Time: 41.382 ms

fiddle

Postgresql相关问答推荐

在Go中,如何在没有数据库包的情况下运行PostgreSQL查询?

如何在PostgreSQL中 Select 最近30天内的开始日期?

PostGresql :正则表达式 Select 其中只有一个正斜杠的行

在连接字符串并将其附加到 PostgreSQL 中的 where 子句时出现语法错误.怎么修?

postgres hierarchy - 用祖先的值填充缺失值

使用 GDB 调试器调试 AGE 代码的过程

计算每行的多列中的非 NULL 元素

PostgreSQL SELECT 结果具有不同的 id,它更喜欢来自另一个表的特定值

使用间隔参数的 go postgres 准备好的语句不起作用

将数组插入 Postgresql 数据库

是否可以使用 pgAdmin4 自动格式化/美化 SQL 查询?

是否有 postgres CLOSEST 运算符?

将 Postgres 与 Grails 一起使用

带有 -C 选项的 pg_restore 不会创建数据库

Postgresql - 在 Big Data 库中使用数组的性能

Mac psql/readline - 未加载库

在 Postgresql 中拆分逗号分隔的字段并对所有结果表执行 UNION ALL

使用 Spring、Hibernate 和 C3P0 管理多租户 Web 应用程序中的连接池

如何减少存储(缩减)我的 RDS 实例?

使用 cte (postgresql) 的结果更新