带传播的 SQL 限制
Posted
技术标签:
【中文标题】带传播的 SQL 限制【英文标题】:SQL limit with spread 【发布时间】:2022-01-20 16:42:57 【问题描述】:有没有办法像LIMIT
那样限制选择,但不是用偏移返回限制,而是用“传播”限制。
例如,如果一个选择返回 1000 行并且我将其限制为 100,那么我从开始到结束每 10 行获取一次。
我知道这需要执行完整的SELECT
,因为 RDBMS 需要遍历所有行才能执行此操作。但是,例如,当我需要每 100 行时返回 100000 行,这样会减少很多传输,并且可以在 RDBMS 上完成工作。
我在 PostgreSQL 数据库上需要这个。
【问题讨论】:
"...从头到尾每隔 10 行获取一次..." -- 在没有ORDER BY
子句的情况下,没有“第一行”、“中间行”或“结束行” ”。引擎可以按任何顺序返回行,这可能会在每次查询执行中发生更改,恕不另行通知。这个问题写的没有意义。
【参考方案1】:
没有与 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 限制的主要内容,如果未能解决你的问题,请参考以下文章