Funguje to:
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
FROM collection
WHERE id = 1);
Nebo podrobnější, ale výhodnější :
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (e).*
FROM collection c, unnest(c.elements) e
WHERE c.id = 1);
Robustnější a vyhýbá se vyhodnocování unnest()
vícekrát. Viz:
Toto funguje také:
SELECT *
FROM element
WHERE ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
FROM collection
WHERE id = 1);
Jádrem problému je, že IN
provedení dílčího dotazu zná dvě samostatné formy. Citace příručky:
Váš dotaz, který selhal řeší na druhou formu, zatímco vy (pochopitelně) očekáváte první. Ale druhý formulář dělá toto:
Můj první a druhý dotaz aby to fungovalo rozložením typu řádku
napravo od operátora. Postgres má tedy tři bigint
hodnoty vlevo a vpravo a je spokojen.
Můj třetí dotaz zprovozní to vnořením typu řádku doleva do jiného konstruktor řádků . Postgres rozloží pouze první úroveň a skončí s jediným složeným typem – odpovídajícím jedinému složenému typu vpravo.
Všimněte si, že klíčové slovo ROW
je vyžadováno pro jedno pole, které balíme. Příručka:
Váš pracovní dotaz se mírně liší, protože poskytuje seznam hodnot vpravo namísto poddotazu (set ). To je jiná implementace s jinou cestou kódu. Dokonce dostane samostatnou kapitolu v návodu . Tato varianta nemá žádnou speciální úpravu pro konstruktor ROW nalevo. Takže to prostě funguje podle očekávání (vámi).
Více ekvivalentních (pracovních) variant syntaxe s = 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[]);
Platí také s (pk1, pk2, pk3)::element_pk_t
nebo ROW(pk1, pk2, pk3)::element_pk_t
Viz:
Protože váš zdroj je pole , Danielův druhý dotaz s (e.pk1, e.pk2, e.pk3) = ANY(c.elements)
přirozeně se hodí.
Ale za sázku na nejrychlejší dotaz , moje peníze jsou na mé druhé variantě, protože očekávám, že bude optimálně využívat index PK.
Jen jako důkaz konceptu. Jak poznamenal a_horse:normalizovaný návrh DB bude pravděpodobně nejlépe škálovat.