PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak dopasować elementy w tablicy typu złożonego?

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ł.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jaki jest zalecany sposób szyfrowania haseł użytkowników w bazie danych?

  2. Dlaczego wszystkie moje tabele w Rails 4/Postgres są tworzone z wymiarem 1?

  3. Zsumuj czas trwania nakładających się okresów z priorytetem, wykluczając samo nakładanie się

  4. Eksportuj określone wiersze z tabeli PostgreSQL jako skrypt INSERT SQL

  5. Jak uzyskać podciąg od czwartego wystąpienia znaku do końca danego ciągu w PSQL