88

我正在尝试从表中获取 15,000 个 ID 的 25 个随机样本。我不是每次都手动按下运行,而是尝试循环。我完全理解不是 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
4

5 回答 5

175

像循环这样的过程元素不是 SQL 语言的一部分,只能在过程语言函数过程(Postgres 11 或更高版本)或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;

关于generate_series()

关于优化随机选择的性能:

于 2013-10-02T21:40:30.020 回答
9

以下是您可以使用的示例:

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$;
于 2019-04-23T19:05:11.533 回答
3

我刚刚遇到了这个问题,虽然它很旧,但我想我会为档案添加一个答案。OP 询问了 for 循环,但他们的目标是从表中收集随机的行样本。对于该任务,Postgres 9.5+ 在 WHERE 上提供了 TABLESAMPLE 子句。这是一个很好的概要:

https://www.2ndquadrant.com/en/blog/tablesample-in-postgresql-9-5-2/

我倾向于使用伯努利,因为它是基于行而不是基于页面的,但最初的问题是关于特定的行数。为此,有一个内置的扩展:

https://www.postgresql.org/docs/current/tsm-system-rows.html

CREATE EXTENSION tsm_system_rows;

然后你可以抓取你想要的任意数量的行:

select * from playtime tablesample system_rows (15);
于 2019-10-12T21:29:22.230 回答
2

我发现使用过程编程语言(如 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()
于 2019-11-05T18:33:28.900 回答
0

使用程序。

CREATE or replace PROCEDURE pg_temp_3.insert_data()
LANGUAGE SQL
BEGIN ATOMIC
INSERT INTO meta_random_sample(col_serial, parent_id)
SELECT t.*
FROM   generate_series(1,25) i
CROSS  JOIN LATERAL (
   SELECT i, parent_id
   FROM    parent_tree order by random() limit 2
   ) t;
END;

调用程序。

call pg_temp_3.insert_data();

PostgreSQL 手册:https ://www.postgresql.org/docs/current/sql-createprocedure.html

于 2021-12-06T13:51:06.690 回答