【问题标题】:Repeatable Pseudorandom Sample of rows in PostgresSQLPostgresQL 中行的可重复伪随机样本
【发布时间】:2020-08-31 14:14:25
【问题描述】:
我想使用随机种子对我的数据的一些子集进行随机抽样,以便它可以重复。目前,我有这个工作减去种子:
select * from my_table
where version is not null
and start_datetime::date >= date('2020-03-16')
and start_datetime::date < date('2020-05-15')
order by random()
limit 10000
现在我想设置一个随机种子,这样我就可以可靠地从此查询中获得相同的结果。
有什么好办法吗?
【问题讨论】:
标签:
sql
postgresql
random
sql-order-by
sql-limit
【解决方案1】:
一个选项使用random function setseed()。如文档中所述:一旦调用此函数,当前会话中后续 random() 调用的结果可通过使用相同参数重新发出 setseed() 来重复。
该技术是使用union all 直接在查询中包含对该函数的调用,然后在外部查询中进行排序。这需要列出要从查询中返回的列。假设您想要列 col1, col2, col3,您的查询将是:
select *
from (
select setseed(0.5) colx, null col1, null col2, null col3
union all
select null, col1, col2, col3
from mytable
where
rpt.assist_detail.version is not null
and start_datetime::date >= date '2020-03-16'
and start_datetime::date < date '2020-05-15'
offset 1
) t
order by random()
limit 10000
offset 1 用于删除第一个子查询生成的行。 setseed()(这里是0.5)的参数可以是-1和1之间的任意值。只要传递相同的值,就会得到相同的排序。
【解决方案2】:
RANDOM() 根据定义是不可重复的。
如果你想再次基于随机值获得相同的排序,你别无选择,只能将随机值存储在某个地方。
我建议您创建自己的表,添加一个整数列,并用随机整数填充:
CREATE TABLE my_random_ordered_sample AS
SELECT
(RANDOM()*10000)::INT AS rand_ord
, *
FROM mytable
WHERE rpt.assist_detail.version IS NOT NULL
AND start_datetime::DATE >= '2020-03-16'::DATE
AND start_datetime::DATE < '2020-05-15'::DATE
;
拥有它后,您可以:
SELECT
all_the
, columns_
, except_the
, ordering_column
, named_rand_ord
FROM my random_ordered_sample
ORDER BY rand_ord;