PostgreSQL의 함수 내에서 SELECT 결과를 반환하는 방법은 무엇입니까?
PostgreSQL에이 함수가 있지만 쿼리 결과를 반환하는 방법을 모르겠습니다.
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;
하지만 PostgreSQL 함수 내에서 쿼리 결과를 반환하는 방법을 모르겠습니다.
반환 유형이이어야 함을 알았 SETOF RECORD습니다. 그러나 반환 명령은 옳지 않습니다.
이를 수행하는 올바른 방법은 무엇입니까?
사용 RETURN QUERY:
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
RETURNS TABLE (txt text -- also visible as OUT parameter inside function
, cnt bigint
, ratio bigint) AS
$func$
BEGIN
RETURN QUERY
SELECT t.txt
, count(*) AS cnt -- column alias only visible inside
, (count(*) * 100) / _max_tokens -- I added brackets
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$ LANGUAGE plpgsql;
요구:
SELECT * FROM word_frequency(123);
설명:
반환 유형을 단순히 레코드로 선언하는 것보다 명시 적으로 정의하는 것이 훨씬 더 실용적입니다. 이렇게하면 모든 함수 호출에 열 정의 목록을 제공 할 필요가 없습니다.
RETURNS TABLE그렇게하는 한 가지 방법입니다. 다른 것들이 있습니다.OUT매개 변수의 데이터 유형은 쿼리에서 반환 된 것과 정확히 일치해야합니다.OUT매개 변수의 이름을 신중하게 선택하십시오 . 거의 모든 곳에서 기능 본문에서 볼 수 있습니다. 충돌이나 예기치 않은 결과를 방지하기 위해 동일한 이름의 열을 테이블 한정합니다. 내 예제의 모든 열에 대해 그렇게했습니다.그러나 매개 변수 와 동일한 이름의 열 별칭 간에 잠재적 인 이름 지정 충돌에 유의하십시오 . 이 특별한 경우 ( ) Postgres는 매개 변수에 대해 열 별칭을 사용합니다 . 하지만 다른 상황에서는 모호 할 수 있습니다. 혼동을 피할 수있는 다양한 방법이 있습니다.
OUTcntRETURN QUERY SELECT ...OUT- SELECT 목록에서 항목의 서수 위치를 사용하십시오
ORDER BY 2 DESC.. 예: - 식을 반복합니다
ORDER BY count(*). - (Not applicable here.) Set the configuration parameter
plpgsql.variable_conflictor use the special command#variable_conflict error | use_variable | use_columnin the function. See:
- SELECT 목록에서 항목의 서수 위치를 사용하십시오
Don't use "text" or "count" as column names. Both are legal to use in Postgres, but "count" is a reserved word in standard SQL and a basic function name and "text" is a basic data type. Can lead to confusing errors. I use
txtandcntin my examples.Added a missing
;and corrected a syntax error in the header.(_max_tokens int), not(int maxTokens)- type after name.While working with integer division, it's better to multiply first and divide later, to minimize the rounding error. Even better: work with
numeric(or a floating point type). See below.
Alternative
This is what I think your query should actually look like (calculating a relative share per token):
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
RETURNS TABLE (txt text
, abs_cnt bigint
, relative_share numeric) 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$ LANGUAGE plpgsql;
The expression sum(t.cnt) OVER () is a window function. You could use a CTE instead of the subquery - pretty, but a subquery is typically cheaper in simple cases like this one.
A final explicit RETURN statement is not required (but allowed) when working with OUT parameters or RETURNS TABLE (which makes implicit use of OUT parameters).
round() with two parameters only works for numeric types. count() in the subquery produces a bigint result and a sum() over this bigint produces a numeric result, thus we deal with a numeric number automatically and everything just falls into place.
Hi please check the below link
https://www.postgresql.org/docs/current/xfunc-sql.html
EX:
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;
'developer tip' 카테고리의 다른 글
| 서버 127.0.0.1 shell / mongo.js에 연결할 수 없습니다. (0) | 2020.09.11 |
|---|---|
| Python egg 파일을 만드는 방법 (0) | 2020.09.10 |
| ScrollView 내의 ViewPager가 올바르게 스크롤되지 않습니다. (0) | 2020.09.10 |
| 크기와 개수를 인수로 취하는 fread / fwrite의 근거는 무엇입니까? (0) | 2020.09.10 |
| OVER_QUERY_LIMIT 응답을받지 않고 20 개 주소를 지오 코딩하려면 어떻게해야합니까? (0) | 2020.09.10 |