我正在尝试从表中获取25个15,000个ID的随机样本。而不是每次都手动按下运行,我正在尝试循环。我完全理解的不是Postgres的最佳用法,但它是我的工具。这就是我到目前为止所做的:
for i in 1..25 LOOP
insert into playtime.meta_random_sample
select i, ID
from tbl
order by random() limit 15000
end loop
答案 0 :(得分:103)
Procedural elements like loops不是SQL语言的一部分,只能在过程语言function,procedure(Postgres 11或更高版本)或{{3}的正文中使用}语句,其中这些附加元素由相应的过程语言定义。默认值为DO
,但PL/pgSQL。
plpgsql示例:
DO
$do$
BEGIN
FOR i IN 1..25 LOOP
INSERT INTO playtime.meta_random_sample
(col_i, col_id) -- declare target columns!
SELECT i, id
FROM tbl
ORDER BY random()
LIMIT 15000;
END LOOP;
END
$do$;
对于可以通过循环解决的许多任务,有一个更短,更快的基于集合的解决方案。纯SQL等效于您的示例:
INSERT INTO playtime.meta_random_sample (col_i, col_id)
SELECT t.*
FROM generate_series(1,25) i
CROSS JOIN LATERAL (
SELECT i, id
FROM tbl
ORDER BY random()
LIMIT 15000
) t;
关于优化随机选择的效果:
答案 1 :(得分:1)
我只是遇到了这个问题,虽然它很旧,但我想我会为档案添加一个答案。 OP询问是否存在循环,但他们的目标是从表中收集随机的行样本。对于该任务,Postgres 9.5+在WHERE上提供了TABLESAMPLE子句。这是一个很好的总结:
https://www.2ndquadrant.com/en/blog/tablesample-in-postgresql-9-5-2/
我倾向于使用Bernoulli,因为它基于行而不是基于页面,但是最初的问题是关于特定的行数。为此,有一个内置扩展程序:
https://www.postgresql.org/docs/current/tsm-system-rows.html
CREATE EXTENSION tsm_system_rows;
然后,您可以获取任意数量的行:
select * from playtime tablesample system_rows (15);
答案 2 :(得分:0)
下面是您可以使用的示例:
create temp table test2 (
id1 numeric,
id2 numeric,
id3 numeric,
id4 numeric,
id5 numeric,
id6 numeric,
id7 numeric,
id8 numeric,
id9 numeric,
id10 numeric)
with (oids = false);
do
$do$
declare
i int;
begin
for i in 1..100000
loop
insert into test2 values (random(), i * random(), i / random(), i + random(), i * random(), i / random(), i + random(), i * random(), i / random(), i + random());
end loop;
end;
$do$;
答案 3 :(得分:0)
我发现使用过程编程语言(例如Python)建立连接并进行这些类型的查询会更加方便。
import psycopg2
connection_psql = psycopg2.connect( user="admin_user"
, password="***"
, port="5432"
, database="myDB"
, host="[ENDPOINT]")
cursor_psql = connection_psql.cursor()
myList = [...]
for item in myList:
cursor_psql.execute('''
-- The query goes here
''')
connection_psql.commit()
cursor_psql.close()