Actually, with the data type jsonb
in Postgres 9.4 or later, this becomes dead simple. Your query would just work (ugly naming convention, code and duplicate names in the output aside).
CREATE TEMP TABLE table_a(a_id int, a int, b jsonb);
INSERT INTO table_a VALUES
(1, 36464, '["874746", "474657"]')
, (2, 36465, '["874748"]')
, (3, 36466, '["874736", "474654"]');
CREATE TEMP TABLE table_b(b_id int, name text, b jsonb);
INSERT INTO table_b VALUES
(1, 'john' , '["8740246", "2474657"]')
, (2, 'mary' , '["874748","874736"]')
, (3, 'clara', '["874736", "474654"]');
Query:
SELECT a_id, a, b.*
FROM table_a a
JOIN table_b b USING (b); -- match on the whole jsonb column
That you even ask indicates you are using the data type json
, for which no equality operator exists:
You just didn't mention the most important details.
The obvious solution is to switch to jsonb
.
is it possible to flatten out b into new rows rather than an array?
Use jsonb_array_elements(jsonb)
or jsonb_array_elements_text(jsonb)
in a LATERAL
join:
SELECT a_id, a, b.b_id, b.name, b_array_element
FROM table_a a
JOIN table_b b USING (b)
, jsonb_array_elements_text(b) b_array_element
This returns only rows matching on the whole array. About LATERAL
:
If you want to match on array elements instead, unnest your arrays before you join.
The whole setup seems to be in dire need of normalization.