sql >> Database >  >> RDS >> PostgreSQL

Hoe jsonb-arrays op te vragen met de IN-operator

Kort antwoord

U kunt de functie jsonb_array_elements() . gebruiken in een laterale samenvoeging en gebruik het resultaat value in complexe uitdrukkingen in de WHERE clausule:

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

Verschillend

De query kan dubbele rijen retourneren wanneer aan de filtervoorwaarden is voldaan in meer dan één element van de array in een enkele rij, bijvoorbeeld

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)    

Daarom kan het redelijk zijn om DISTINCT . te gebruiken in de SELECT lijst:

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

of EXISTS in de WHERE clausule, die misschien wat sneller is:

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

U kunt ook overeenkomende array-elementen selecteren in gevallen waarin deze informatie nodig is:

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)

Prestaties

De jsonb_array_elements() functie is duur. Voor grotere tabellen kan het gebruik van de functie twijfelachtig zijn vanwege de zware serverbelasting en de lange uitvoeringstijd van een query.

Hoewel een GIN-index kan worden gebruikt voor zoekopdrachten met de @> operator:

CREATE INDEX ON test USING GIN (test_content)

bij de functie is dit niet mogelijk. Query's die door de index worden ondersteund, kunnen tot enkele tientallen keren sneller zijn dan die waarbij de functie wordt gebruikt.




  1. Verstuur e-mails met bijlagen in SQL Server (T-SQL)

  2. Compleet gebruikersregistratiesysteem met behulp van PHP en MySQL-database

  3. 2 manieren om de korte maandnaam van een datum in MariaDB te krijgen

  4. Buitenlandse PostgreSQL-sleutel bestaat niet, probleem met overerving?