Mam taką funkcję w PostgreSQL, ale nie wiem jak zwrócić wynik zapytania:
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;
Ale nie wiem, jak zwrócić wynik zapytania wewnątrz funkcji PostgreSQL.
Odkryłem, że typem zwrotu powinien być SETOF RECORD
, prawda? Ale polecenie powrotu jest nieprawidłowe.
Jaki jest właściwy sposób, aby to zrobić?
sql
postgresql
return
plpgsql
return-type
Renato Dinhani
źródło
źródło
LANGUAGE SQL
.Odpowiedzi:
Zastosowanie
RETURN QUERY
:Połączenie:
Wyjaśnienie:
O wiele bardziej praktyczne jest jawne zdefiniowanie typu zwracanego niż zwykłe zadeklarowanie go jako rekordu. W ten sposób nie musisz podawać listy definicji kolumn przy każdym wywołaniu funkcji.
RETURNS TABLE
jest jednym ze sposobów, aby to zrobić. Są inni. Typy danychOUT
parametrów muszą dokładnie odpowiadać temu, co jest zwracane przez zapytanie.OUT
Uważnie wybieraj nazwy parametrów. Są widoczne w korpusie funkcji prawie wszędzie. Kwalifikuj kolumny o tej samej nazwie, aby uniknąć konfliktów lub nieoczekiwanych wyników. Zrobiłem to dla wszystkich kolumn w moim przykładzie.Zwróć jednak uwagę na potencjalny konflikt nazw między
OUT
parametremcnt
a aliasem kolumny o tej samej nazwie. W tym konkretnym przypadku (RETURN QUERY SELECT ...
) Postgres używa aliasu kolumny zamiastOUT
parametru w obie strony. Może to być jednak niejednoznaczne w innych kontekstach. Istnieje wiele sposobów uniknięcia nieporozumień:ORDER BY 2 DESC
. Przykład:ORDER BY count(*)
.plpgsql.variable_conflict
lub użyj specjalnego polecenia#variable_conflict error | use_variable | use_column
w funkcji. Widzieć:Nie używaj „tekst” ani „liczba” jako nazw kolumn. Oba są legalne w Postgresie, ale „count” jest słowem zastrzeżonym w standardowym SQL, a nazwa funkcji i „tekst” to podstawowy typ danych. Może prowadzić do mylących błędów. Używam
txt
icnt
w moich przykładach.Dodano brakujący
;
i poprawiono błąd składni w nagłówku.(_max_tokens int)
, nie(int maxTokens)
- wpisz po nazwie .Podczas pracy z dzieleniem całkowitoliczbowym lepiej jest najpierw pomnożyć, a później podzielić, aby zminimalizować błąd zaokrąglania. Jeszcze lepiej: pracuj z
numeric
(lub typem zmiennoprzecinkowym). Zobacz poniżej.Alternatywny
To jest to, co ja myślę zapytanie powinno wyglądać w rzeczywistości (obliczenie względnego udziału za żeton ):
Wyrażenie
sum(t.cnt) OVER ()
jest funkcją okna . Ty mógł użyć CTE zamiast podkwerendzie - ładna, ale podzapytanie jest zazwyczaj tańsze w prostych przypadkach takich jak ten.Ostateczna jawna
RETURN
instrukcja nie jest wymagana (ale dozwolona) podczas pracy zOUT
parametrami lubRETURNS TABLE
(co powoduje niejawne użycieOUT
parametrów).round()
z dwoma parametrami działa tylko dlanumeric
typów.count()
w podzapytaniu dajebigint
wynik, asum()
over tobigint
dajenumeric
wynik, więc mamy do czynienia znumeric
liczbą automatycznie i wszystko po prostu układa się na swoim miejscu.źródło
RETURN;
wcześniejEND;
, przynajmniej ja tak zrobiłem - ale robię UNION, więc nie jestem pewien, czy to sprawia, że jest inaczej.RETURN
. Naprawiono niepowiązany błąd i dodano kilka ulepszeń podczas pracy.Cześć, sprawdź poniższy link
https://www.postgresql.org/docs/current/xfunc-sql.html
DAWNY:
źródło