带传播的 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。见:

Fast way to discover the row count of a table in PostgreSQL Best way to select random rows PostgreSQL

【讨论】:

以上是关于带传播的 SQL 限制的主要内容,如果未能解决你的问题,请参考以下文章

“模拟”用户未传播到 SQL Server 2000

SQL Server 是不是在复杂视图中传播 WHERE 条件?

CRMEB知识付费系统v1.2发布上线直播带课功能

SQL/DAX 中的多父层次结构传播

从 DB2 存储过程出口处理程序传播默认 SQL 异常

没错,纯SQL查询语句可以实现神经网络