programing

루프에 대한 게시물

linuxpc 2023. 5. 31. 15:24
반응형

루프에 대한 게시물

저는 테이블에서 15,000개의 아이디를 무작위로 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

루프같은 절차적 요소는 SQL 언어의 일부가 아니며 절차적 언어 함수, 절차(Postgres 11 이상) 또는 문의 본문 내에서만 사용할 수 있습니다. 여기서 이러한 추가 요소는 각 절차적 언어에 의해 정의됩니다.기본값은 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;

정보:

랜덤 선택의 성능 최적화 정보:

다음은 사용할 수 있는 예입니다.

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$;

저는 이 질문에 부딪혔고, 오래된 질문이지만, 아카이브에 대한 답변을 추가하기로 했습니다.OP는 루프에 대해 물었지만, 그들의 목표는 테이블에서 임의의 행 샘플을 수집하는 것이었습니다.이 작업을 위해 Postgres 9.5+는 WHERE에 TABLESSAMPLE 절을 제공합니다.여기 좋은 요약이 있습니다.

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);

절차적 프로그래밍 언어(예: 파이썬)를 사용하여 연결하고 이러한 유형의 쿼리를 수행하는 것이 더 편리합니다.

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()

UUID Array, For loop, Case condition 및 Enum 데이터 업데이트와 관련된 하나의 복잡한 postgres 함수입니다.이 기능은 각 행을 구문 분석하고 조건을 확인하고 개별 행을 업데이트합니다.

CREATE OR REPLACE FUNCTION order_status_update() RETURNS void AS $$
DECLARE
  oid_list uuid[];
  oid uuid;
BEGIN
  SELECT array_agg(order_id) FROM order INTO oid_list;
  FOREACH uid IN ARRAY uid_list
  LOOP
    WITH status_cmp AS (select COUNT(sku)=0 AS empty, 
                    COUNT(sku)<COUNT(sku_order_id) AS partial, 
                    COUNT(sku)=COUNT(sku_order_id) AS full 
                    FROM fulfillment 
                    WHERE order_id=oid)
    UPDATE order
    SET status=CASE WHEN status_cmp.empty THEN 'EMPTY'::orderstatus
    WHEN status_cmp.full THEN 'FULL'::orderstatus
    WHEN status_cmp.partial THEN 'PARTIAL'::orderstatus
    ELSE null
    END 
    FROM status_cmp
    WHERE order_id=uid;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

위의 기능을 실행하는 방법

SELECT order_status_update();

절차를 사용합니다.

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

언급URL : https://stackoverflow.com/questions/19145761/postgres-for-loop

반응형