#sql #postgresql #where-clause #greatest-n-per-group #sql-function
#sql #postgresql #where-предложение #наибольшее число пользователей на группу #sql-функция
Вопрос:
Я пытаюсь создать функцию postgreql, я немного запутался в том, какой формат синтаксиса использовать, когда я передаю оператор select, который принимает параметр (этот параметр может быть строкой или списком строк)
Вот исходный запрос select, который я использовал ранее, с placeholders
моим параметром. Этот выбор отлично подходит для меня!
SELECT DISTINCT ON (symbol) symbol,
next_dividend_date, ex_dividend_date
FROM api.security_stats
WHERE api.security_stats.symbol
IN ({placeholders})
ORDER BY symbol, date desc;
Проблема в том, что я попытался преобразовать приведенное выше в полезную функцию, где пользователи могут вводить параметр для функции. Однако я не могу заставить синтаксис работать. Кроме того, в документации psql для функций есть много примеров синтаксиса. Я не уверен, какой из них использовать для моего случая?
CREATE FUNCTION dividend(stocks char)
RETURNS TABLE(symbol char, next_dividend_date date, ex_dividend_date date) AS $
SELECT DISTINCT ON (symbol) symbol, next_dividend_date, ex_dividend_date
FROM api.security_stats
WHERE api.security_stats.symbol
IN ({stocks}) ORDER BY symbol, date desc)
$ LANGUAGE SQL;
Я пытаюсь разрешить, чтобы параметр, stocks
, вводился пользователем-клиентом.
Спасибо за любую помощь!
Ответ №1:
Я думаю, вы хотите что-то вроде:
create function dividend(p_stocks char)
returns table(symbol char, next_dividend_date date, ex_dividend_date date)
as $
select distinct on (symbol) symbol, next_dividend_date, ex_dividend_date
from api.security_stats
where api.security_stats.symbol = any(string_to_array($1, ','))
order by symbol, date desc
$ language sql;
Это функция SQL, возвращающая таблицу; вы можете ссылаться на входной аргумент с позиционной нотацией $1
.
Между строками вашего вопроса я понимаю, что аргумент представляет собой строку, разделенную запятыми, поэтому я добавил дополнительный шаг для ее преобразования в массив, который затем можно искать с помощью operator any
.
Или, если вы хотите передать свой ввод в виде массива:
create function dividend(p_stocks text[])
returns table(symbol char, next_dividend_date date, ex_dividend_date date)
as $
select distinct on (symbol) symbol, next_dividend_date, ex_dividend_date
from api.security_stats
where api.security_stats.symbol = any($1)
order by symbol, date desc
$ language sql;
Комментарии:
1. Большое вам спасибо за то, что все разъяснили. Глядя на этот фрагмент, теперь я понимаю параметры функции для postgres. Я еще не тестировал его, но скоро прокомментирую и дам вам знать!
2. Я могу заставить этот запрос работать! большое вам спасибо, однако у меня есть вопрос: допускает ли этот метод только одну строку в параметре? Что делать, если у меня есть список строк. Например,
select dividend('MSFT');
это отлично работает! Но когда я пытаюсь сделать,select dividend('MSFT', 'AAPL');
Функция, похоже, не работает, я должен структурировать ввод по-другому?3. @Dre: функция принимает строку CSV, так что это будет:
select dividend('MSFT,AAPL')
. Или вы можете изменить код функции, чтобы принимать непосредственно массив, и вызвать его следующим образом:select divident(array['MSFT', 'AAPL'])
4. Ради любопытства, как будет выглядеть другая функция, которая напрямую принимает массив? Я думаю, что было бы лучшим вариантом для моего конкретного варианта использования. Если я использую этот запрос как часть веб-приложения, я думаю, формат массива может быть лучше? Меньше преобразования данных.
5. вы очень хорошо настроили меня для моих следующих функций, большое вам спасибо за помощь!