在 PostgreSQL 中采样

Sampling in PostgreSQL

我正在寻找 PostgreSQL 中随机抽样的可能方法。我找到了几种方法来做到这一点,各有优缺点。天真的方法是:

select * from Table_Name
order by random()
limit 10;

另一种更快的方法是:

select * from Table_Name
WHERE random() <= 0.01
order by random()
limit 10;

(尽管 0.01 取决于 table 大小和样本大小;这只是一个示例。)

在这两个查询中,都会为每一行生成一个随机数,并根据这些随机生成的数进行排序。然后在排序的数字中选择前10个作为最终结果,所以我认为这些应该是无放回抽样。

现在我想做的是以某种方式将这种抽样方法变成有放回抽样。这怎么可能?或者PostgreSQL中有没有其他随机抽样的替换方法?

我不得不说我确实知道这可能是如何实现的,但我不知道如何在 postgresql 中实现它,这是我的想法:
如果不是生成一个随机值而是生成S个随机值,其中S是样本大小,然后对所有随机生成的值进行排序,它将是有放回的采样。(我不知道我是否正确)
此时我不介意查询的性能。

这可以通过将随机值映射到行号来实现。如果恰好对应的同一个随机数出现 N 次,则同一行可以被采样 N 次。这是一个 CTE 实现:

with 
 rows as (select *,row_number() over() as rn from tablename order by random()),
 w(num) as (select (random()*(select count(*) from rows))::int+1
              from generate_series(1,10)) 
select rows.* from rows join w on rows.rn = w.num;