To działa:
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
FROM collection
WHERE id = 1);
Lub bardziej gadatliwy, ale najlepiej :
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (e).*
FROM collection c, unnest(c.elements) e
WHERE c.id = 1);
Bardziej niezawodny i unikający oceny unnest()
wiele razy. Zobacz:
To też działa:
SELECT *
FROM element
WHERE ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
FROM collection
WHERE id = 1);
Sednem problemu jest to, że IN
przyjmowanie podzapytania zna dwie odrębne formy. Cytując instrukcję:
Twoje nieudane zapytanie przechodzi do drugiej formy, podczas gdy ty (co zrozumiałe) oczekujesz pierwszej. Ale robi to druga forma:
Moje pierwsze i drugie zapytanie spraw, aby działało, dekomponując typ wiersza
po prawej stronie operatora. Więc Postgres ma trzy bigint
wartości lewe i prawe i jest spełniony.
Moje trzecie zapytanie sprawia, że działa, zagnieżdżając typ wiersza po lewej stronie w innym konstruktor wierszy . Postgres rozkłada tylko pierwszy poziom i kończy z pojedynczym typem złożonym — dopasowując pojedynczy typ złożony po prawej stronie.
Zwróć uwagę, że słowo kluczowe ROW
jest wymagane dla pojedynczego pola, które oklejamy. Podręcznik:
Twoje zapytanie robocze jest nieco inny, ponieważ zawiera listę wartości po prawej stronie zamiast podzapytania (ustaw ). To inna implementacja o innej ścieżce kodu. Dostaje nawet osobny rozdział w podręczniku . Ten wariant nie ma specjalnego traktowania dla konstruktora ROW po lewej stronie. Więc działa zgodnie z oczekiwaniami (przez Ciebie).
Więcej równoważnych (działających) wariantów składni z = 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[]);
Działa również z (pk1, pk2, pk3)::element_pk_t
lub ROW(pk1, pk2, pk3)::element_pk_t
Zobacz:
Ponieważ Twoim źródłem jest tablica , drugie zapytanie Daniela z (e.pk1, e.pk2, e.pk3) = ANY(c.elements)
nadaje się naturalnie.
Ale postawić na najszybsze zapytanie , moje pieniądze są na moim drugim wariancie, ponieważ spodziewam się, że optymalnie wykorzysta indeks PK.
Podobnie jak dowód koncepcji. Jak skomentował a_koń:znormalizowany projekt bazy danych prawdopodobnie będzie się najlepiej skalował.