У меня есть эта функция в 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
, верно? Но команда возврата неверна.
Как правильно это сделать?
sql
postgresql
return
plpgsql
return-type
Ренато Динхани
источник
источник
LANGUAGE SQL
.Ответы:
Использование
RETURN QUERY
:Вызов:
Пояснение:
Это гораздо более практично явно определить тип возвращаемого значения, чем просто объявить его как запись. Таким образом, вам не нужно предоставлять список определений столбцов при каждом вызове функции.
RETURNS TABLE
это один из способов сделать это. Есть и другие. Типы данныхOUT
параметров должны точно соответствовать тому, что возвращает запрос.OUT
Тщательно выбирайте имена для параметров. Они видны в теле функции практически везде. Столбцы с одинаковыми именами, определяемые таблицей, чтобы избежать конфликтов или неожиданных результатов. Я сделал это для всех столбцов в моем примере.Но обратите внимание на потенциальный конфликт имен между
OUT
параметромcnt
и псевдонимом столбца с тем же именем. В этом конкретном случае (RETURN QUERY SELECT ...
) Postgres вOUT
любом случае использует псевдоним столбца над параметром. Однако в других контекстах это может быть неоднозначным. Есть несколько способов избежать путаницы:ORDER BY 2 DESC
. Пример:ORDER BY count(*)
.plpgsql.variable_conflict
или используйте специальную команду#variable_conflict error | use_variable | use_column
в функции. Видеть:Не используйте «текст» или «счет» в качестве имен столбцов. Оба варианта разрешены для использования в Postgres, но «count» - зарезервированное слово в стандартном SQL, а имя базовой функции и «text» - это базовый тип данных. Может привести к сбивающим с толку ошибкам. Использую
txt
иcnt
в своих примерах.Добавил отсутствующий
;
и исправил синтаксическую ошибку в шапке.(_max_tokens int)
, а не(int maxTokens)
- введите после имени .При работе с целочисленным делением лучше сначала умножить, а потом разделить, чтобы минимизировать ошибку округления. Еще лучше: работать с
numeric
(или типом с плавающей запятой). Увидеть ниже.Альтернатива
Вот как, на мой взгляд, должен выглядеть ваш запрос (расчет относительной доли на токен ):
Выражение
sum(t.cnt) OVER ()
- это оконная функция . Вы можете использовать CTE вместо подзапроса - красиво, но подзапрос обычно дешевле в простых случаях, подобных этому.Заключительный явный
RETURN
оператор не требуется (но разрешен) при работе сOUT
параметрами илиRETURNS TABLE
(при неявном использованииOUT
параметров).round()
с двумя параметрами работает только дляnumeric
типов.count()
в подзапросе выдаетbigint
результат, аsum()
над этимbigint
даетnumeric
результат, поэтому мыnumeric
автоматически обрабатываем число, и все просто становится на свои места.источник
RETURN;
до этогоEND;
, по крайней мере, я сделал - но я делаю UNION, поэтому я не уверен, что это отличает его.RETURN
. Исправлена не связанная с этим ошибка и добавлены некоторые улучшения, пока она была на ней.Привет, пожалуйста, проверьте ссылку ниже
https://www.postgresql.org/docs/current/xfunc-sql.html
EX:
источник