SQL 点差限制

SQL limit with spread

有没有办法像 LIMIT 那样限制 select 离子,但不是用偏移返回限制,而是用“扩散”限制。

例如,如果 select returns 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

由于window定义中没有ORDER BY,行号根据查询的ORDER BY分配。
如果根本没有ORDER BY,您将得到任意行顺序。那仍然是某种命令,结果就在你手中。

您可以使用 TABLESAMPLE 语法对个人 table 应用那种过滤器

SELECT * FROM tbl TABLESAMPLE SYSTEM (10);  -- roughly 10 %

或者:

SELECT * FROM tbl TABLESAMPLE BERNOULLI (10);  -- roughly 10 %

SYSTEM更快,BERNOULLI更随机。

您甚至可以对同一查询中的多个 table 应用 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