sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan forespørges jsonb-arrays med IN-operator

Kort svar

Du kan bruge funktionen jsonb_array_elements() i en lateral sammenføjning og brug dens resultat value i komplekse udtryk i WHERE klausul:

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')

Særskilt

Forespørgslen kan returnere duplikerede rækker, når filterbetingelserne er opfyldt i mere end ét element i arrayet i en enkelt række, f.eks.

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |                          test_content                          
--------------------------------------+----------------------------------------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
(2 rows)    

Derfor kan det være rimeligt at bruge DISTINCT i SELECT liste:

SELECT DISTINCT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

eller EXISTS i WHERE klausul, som kan være en smule hurtigere:

SELECT t.*
FROM test t
WHERE EXISTS (
    SELECT 
    FROM jsonb_array_elements(test_content)
    WHERE value->>'label' IN ('a', 'b')
    )

Du kan også vælge matchende array-elementer i tilfælde, hvor disse oplysninger er nødvendige:

SELECT id, value
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |             value             
--------------------------------------+-------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "a", "label1": "1"}
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "b", "label1": "2"}
(2 rows)

Ydeevne

jsonb_array_elements() funktion er dyr. For større tabeller kan brugen af ​​funktionen være tvivlsom på grund af stor serverbelastning og den lange eksekveringstid af en forespørgsel.

Mens et GIN-indeks kan bruges til forespørgsler med @> operatør:

CREATE INDEX ON test USING GIN (test_content)

i tilfælde af funktionen er dette ikke muligt. Forespørgsler understøttet af indekset kan være op til flere dusin gange hurtigere end dem, der bruger funktionen.




  1. LISTAGG i Oracle for at returnere forskellige værdier

  2. Når du bruger GETDATE() mange steder, er det så bedre at bruge en variabel?

  3. Hurtigere måde at indsætte, via script, i Oracle?

  4. Sådan eksporteres resultaterne af en forespørgsel ved hjælp af MySQL Workbench