programing

PostgreSQL의 함수 내부에서 SELECT 결과를 반환하는 방법은 무엇입니까?

topblog 2023. 5. 8. 21:47
반응형

PostgreSQL의 함수 내부에서 SELECT 결과를 반환하는 방법은 무엇입니까?

나는 이 기능을 Postgre에 가지고 있습니다.SQL, 하지만 쿼리 결과를 반환하는 방법을 모르겠습니다.

CREATE OR REPLACE FUNCTION wordFrequency(maxTokens INTEGER)
  RETURNS SETOF RECORD AS
$$
BEGIN
    SELECT text, count(*), 100 / maxTokens * count(*)
    FROM (
        SELECT text
    FROM token
    WHERE chartype = 'ALPHABETIC'
    LIMIT maxTokens
    ) as tokens
    GROUP BY text
    ORDER BY count DESC
END
$$
LANGUAGE plpgsql;

하지만 Postgre 내부에서 쿼리 결과를 반환하는 방법을 모르겠습니다.SQL 함수입니다.

반품 유형은 다음과 같아야 합니다.SETOF RECORD,그렇죠?그러나 반환 명령이 올바르지 않습니다.

이를 위한 올바른 방법은 무엇입니까?

사용:

CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
  RETURNS TABLE (txt   text   -- also visible as OUT param in function body
               , cnt   bigint
               , ratio bigint)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT t.txt
        , count(*) AS cnt                 -- column alias only visible in this query
        , (count(*) * 100) / _max_tokens  -- I added parentheses
   FROM  (
      SELECT t.txt
      FROM   token t
      WHERE  t.chartype = 'ALPHABETIC'
      LIMIT  _max_tokens
      ) t
   GROUP  BY t.txt
   ORDER  BY cnt DESC;                    -- potential ambiguity 
END
$func$;

통화:

SELECT * FROM word_frequency(123);

반환 유형을 명시적으로 정의하는 것이 제네릭 반환보다 훨씬 실용적입니다.record이렇게 하면 모든 함수 호출에 열 정의 목록을 제공할 필요가 없습니다.RETURNS TABLE 그렇게 하는 한 가지 방법입니다.다른 사람들도 있습니다.데이터 유형:OUT매개 변수는 쿼리에서 반환된 것과 정확히 일치해야 합니다.

이름 선택OUT파라미터를 신중하게 지정합니다.이들은 거의 모든 기능 본체에서 볼 수 있습니다.충돌이나 예상치 못한 결과를 방지하기 위해 동일한 이름의 테이블 수식 열.예제의 모든 열에 대해 이 작업을 수행했습니다.

그러나 두 그룹 사이의 잠재적인 명명 충돌에 유의하십시오.OUT매개 변수cnt동일한 이름의 열 별칭이 있습니다.이 경우(RETURN QUERY SELECT ...Postgres는 위에 열 별칭을 사용합니다.OUT매개 변수는 어느 쪽이든.하지만 이것은 다른 맥락에서 모호할 수 있습니다.혼동을 방지하는 다양한 방법이 있습니다.

  1. SELECT 목록에서 항목의 순서 위치를 사용합니다.ORDER BY 2 DESC예:
  2. 식을 반복합니다.ORDER BY count(*).
  3. (여기서는 필요하지 않습니다.)구성 매개 변수 설정plpgsql.variable_conflict또는 특수 명령을 사용합니다.#variable_conflict error | use_variable | use_column기능상참조:

열 이름으로 "텍스트" 또는 "카운트"를 사용하지 마십시오.둘 다 Postgres에서 사용할 수 있지만 "count"는 표준 SQL에서 예약된 단어이고 기본 함수 이름이며 "text"는 기본 데이터 형식입니다.혼란스러운 오류로 이어질 수 있습니다.사용합니다txt그리고.cnt제 예에서, 당신은 좀 더 명확한 이름을 원할 수도 있습니다.

누락 추가;헤더의 구문 오류를 수정했습니다. (_max_tokens int),것은 아니다.(int maxTokens)이름 뒤에 데이터 형식을 입력합니다.

정수 나눗셈을 사용할 때는 반올림 오차를 최소화하기 위해 먼저 곱셈하고 나중에 나눗셈하는 것이 좋습니다.또는 관련 작업numeric또는 부동 소수점 유형입니다.아래를 참조하십시오.

대안

다음과 같이 쿼리가 실제로 이루어져야 한다고 생각합니다(토큰당 상대적 공유 계산).

CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
  RETURNS TABLE (txt            text
               , abs_cnt        bigint
               , relative_share numeric)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT t.txt, t.cnt
        , round((t.cnt * 100) / (sum(t.cnt) OVER ()), 2)  -- AS relative_share
   FROM  (
      SELECT t.txt, count(*) AS cnt
      FROM   token t
      WHERE  t.chartype = 'ALPHABETIC'
      GROUP  BY t.txt
      ORDER  BY cnt DESC
      LIMIT  _max_tokens
      ) t
   ORDER  BY t.cnt DESC;
END
$func$;

그표은라는 sum(t.cnt) OVER ()는 창 기능입니다.하위 쿼리 대신 CTE를 사용할 수 있습니다.예쁘지만 하위 쿼리는 일반적으로 이와 같은 간단한 경우(대부분 Postgres 12 이전)에 더 저렴합니다.

관련 작업을 수행할 때 최종 명시적 진술은 필요하지 않습니다(그러나 허용됨).OUT 또는 매개변또는수RETURNS TABLE((으를 암묵적으로 OUT매개 변수)를 선택합니다.

round() 매개 변수가 두 개인 경우 유형에만 사용할 수 있습니다. count()▁a다가 생성됩니다.bigint와 a.sum() 이로에bigint합니다.numeric결과, 따라서 우리는 처리합니다.numeric자동으로 번호를 매기고 모든 것이 제자리에 들어맞습니다.

설명서는 다음 링크를 참조하십시오.

https://www.postgresql.org/docs/current/xfunc-sql.html

예:

    CREATE FUNCTION sum_n_product_with_tab (x int)
    RETURNS TABLE(sum int, product int) AS $$
        SELECT $1 + tab.y, $1 * tab.y FROM tab;
    $$ LANGUAGE SQL;

언급URL : https://stackoverflow.com/questions/7945932/how-to-return-result-of-a-select-inside-a-function-in-postgresql

반응형