有没有一种方法可以像 LIMIT
一样限制选择,但不是用偏移量返回限制,而是用“spread”进行限制。
例如,如果一个选择返回 1000 行,而我将其限制为 100,那么我从开始到结束每 10 行都会得到一次。
我知道这需要执行完整的SELECT
,因为 RDBMS 需要遍历所有行才能执行此操作。但是,例如,当我需要每 100 行时,不是返回 100000 行,而是会减少很多传输,并且可以在 RDBMS 上完成工作。
我需要在 PostgreSQL 数据库上执行此操作。
最佳答案
没有内置语法可以执行与LIMIT
/ OFFSET
相关的操作。 (也不适用于标准 SQL FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }]
)。
您可以通过 modulo operator %
实现您的目标:
SELECT *
FROM (
SELECT row_number() OVER () AS rn, ... original SELECT list
FROM ... -- original query
) sub
WHERE rn%10 = 0 -- every 10th row
由于窗口定义中没有ORDER BY
,因此根据查询的ORDER BY
分配行号。
如果根本没有ORDER BY
,您将得到任意的行顺序。这仍然是某种命令,结果并不在你的掌控之中。
您可以使用TABLESAMPLE
在单个表格上应用这种过滤器。语法。
SELECT * FROM tbl TABLESAMPLE SYSTEM (10); -- roughly 10 %
或者:
SELECT * FROM tbl TABLESAMPLE BERNOULLI (10); -- roughly 10 %
SYSTEM
速度更快,BERNOULLI
更加随机。
您甚至可以在同一查询中的多个表上应用TABLESAMPLE
过滤器,例如:
SELECT *
FROM tbl1 TABLESAMPLE SYSTEM (10)
JOIN tbl2 TABLESAMPLE BERNOULLI (10) USING (big_id);
但是生成的行数可能会有很大差异。要获取给定的行数,请考虑附加模块 tsm_system_rows
反而。请参阅:
关于SQL 限制与扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70398543/