Dette virker:
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
FROM collection
WHERE id = 1);
Eller mere omfattende, men at foretrække :
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (e).*
FROM collection c, unnest(c.elements) e
WHERE c.id = 1);
Mere robust og undgår at evaluere unnest()
flere gange. Se:
Dette virker også:
SELECT *
FROM element
WHERE ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
FROM collection
WHERE id = 1);
Kernen i problemet er, at IN
tager en underforespørgsel kender to separate former. Citerer manualen:
Din mislykkede forespørgsel løser sig til den anden form, mens du (forståeligt nok) forventer den første. Men den anden form gør dette:
Min første og anden forespørgsel få det til at fungere ved at dekomponere rækketypen
til højre for operatøren. Så Postgres har tre bigint
værdier venstre og højre og er tilfreds.
Min tredje forespørgsel får det til at fungere ved at indlejre rækketypen til venstre i en anden rækkekonstruktør . Postgres nedbryder kun det første niveau og ender med en enkelt sammensat type - matchende den enkelte sammensatte type til højre.
Bemærk, at søgeordet ROW
er påkrævet for det enkelte felt, vi pakker. Manualen:
Din arbejdsforespørgsel er subtilt anderledes, da det giver en liste af værdier til højre i stedet for en underforespørgsel (indstil ). Det er en anden implementering, der tager en anden kodesti. Den får endda et separat kapitel i manualen . Denne variant har ingen særlig behandling for en ROW-konstruktør til venstre. Så det fungerer bare som forventet (af dig).
Mere ækvivalente (fungerende) syntaksvarianter med = ANY
:
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY ('{"(1,2,3)","(2,3,4)"}'::element_pk_t[]);
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3)::element_pk_t,(2,3,4)::element_pk_t]);
SELECT * FROM element
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3),(2,3,4)]::element[]);
Også gyldig med (pk1, pk2, pk3)::element_pk_t
eller ROW(pk1, pk2, pk3)::element_pk_t
Se:
Da din kilde er en matrix , Daniels anden forespørgsel med (e.pk1, e.pk2, e.pk3) = ANY(c.elements)
giver sig naturligt.
Men for et væddemål på den hurtigste forespørgsel , mine penge er på min anden variant, fordi jeg forventer, at den bruger PK-indekset optimalt.
Bare som proof of concept. Som en hest kommenterede:et normaliseret DB-design vil sandsynligvis skaleres bedst.