Det kan du opnå med en simpel SQL-funktion. Nøglefunktion er funktionen generate_subscripts()
:
CREATE OR REPLACE FUNCTION f_attendance(_arr2d int[])
RETURNS SETOF attendance AS
$func$
SELECT a.*
FROM generate_subscripts($1, 1) i
JOIN attendance a ON a.class = $1[i][1]
AND a.section = $1[i][2]
$func$ LANGUAGE ROWS 10 sql STABLE;
Ring til:
SELECT * FROM f_attendance(ARRAY[[1,1],[2,2]]);
Eller det samme med en matrix literal - hvilket er mere bekvemt i nogle sammenhænge, især med forberedte udsagn:
SELECT * FROM f_attendance('{{1,1},{2,2}}');
Funktionen altid forventer et 2D-array. Selvom du passerer et enkelt par, skal du indlejre det:
SELECT * FROM f_attendance('{{1,1}}');
Revision af din implementering
-
Du lavede funktionen
VOLATILE
, men det kan væreSTABLE
. Per dokumentation:På grund af denne snapshot-adfærd, en funktion, der kun indeholder
SELECT
kommandoer kan sikkert markeres medSTABLE
.Relateret:
- Sådan overføres en parameter til en datofunktion
-
Du bruger også
LANGUAGE plpgsql
i stedet forsql
, hvilket giver mening, hvis du udfører funktionen flere gange i samme session. Men så skal du også gøre denSTABLE
eller du mister den potentielle præstationsfordel. Manualen endnu en gang:STABLE
ogIMMUTABLE
funktioner bruger et øjebliksbillede etableret ved starten af den kaldende forespørgsel, hvorimod VOLATILE funktioner opnår et nyt øjebliksbillede i starten af hver forespørgsel, de udfører. -
Din
EXPLAIN
output viser en Kun indeksscanning , ikke en sekventiel scanning, som du har mistanke om i din kommentar. -
Der er også et sorteringstrin i din
EXPLAIN
output, der ikke matcher den kode, du viser. Er du sikker på, at du har kopieret den rigtigeEXPLAIN
produktion? Hvordan fik du det alligevel? PL/pgSQL-funktioner er sorte bokse tilEXPLAIN
. Brugte duauto_explain
? Detaljer:- Postgres-forespørgselsplan for en UDF-invokation skrevet i pgpsql
-
Postgres-forespørgselsplanlæggeren har ingen idé om, hvor mange array-elementer den beståede parameter vil have, så det er svært at planlægge forespørgslen, og det kan som standard være en sekventiel scanning (afhængigt af flere faktorer). Du kan hjælpe ved at angive det forventede antal rækker. Hvis du typisk ikke har mere end 10 varer, skal du tilføje
ROWS 10
som jeg gjorde nu ovenfor. Og test igen.