Reputation: 337
I have a table with JSONB column storing JSONB arrays/strings (value_r
column in the below example). What would be the simplest (and efficent) way to sort only content of JSONB arrays within JSONB column (storing also strings)?
I've been looking for the simplest method (as query, or procedure is needed?) because I have to apply this in more complicated SQL code.
Here is the test code:
CREATE TABLE test_table (
id integer,
ordinality bigint,
key_r text,
value_r jsonb
);
INSERT INTO test_table VALUES (1, 1, 'carType', '"sedan"');
INSERT INTO test_table VALUES (1, 1, 'equipment', '["AT", "AC"]');
INSERT INTO test_table VALUES (1, 2, 'extra', '["GPS"]');
INSERT INTO test_table VALUES (1, 2, 'carType', '"hatchback"');
INSERT INTO test_table VALUES (2, 1, 'carType', '"sedan"');
INSERT INTO test_table VALUES (2, 1, 'equipment', '["BB", "AA"]');
INSERT INTO test_table VALUES (3, 1, 'carType', '"hatchback"');
INSERT INTO test_table VALUES (3, 1, 'equipment', '["AT"]');
Edit:
Expected results - because I am going to compare arrays from two different tables, thus I would like to unify content of arrays, so '["AT", "AC"]'
and '["AC", "AT"]'
become the same. Frankly speaking, it doesn't matter which "default" sort is used: ASC or DESC - I will just have to run the same SQL query/procedure for two tables to make it consistent and comparable. Let's say that these are expected results:
INSERT INTO test_table VALUES (1, 1, 'carType', '"sedan"');
INSERT INTO test_table VALUES (1, 1, 'equipment', '["AC", "AT"]'); -- change here
INSERT INTO test_table VALUES (1, 2, 'extra', '["GPS"]');
INSERT INTO test_table VALUES (1, 2, 'carType', '"hatchback"');
INSERT INTO test_table VALUES (2, 1, 'carType', '"sedan"');
INSERT INTO test_table VALUES (2, 1, 'equipment', '["AA", "BB"]'); -- change here
INSERT INTO test_table VALUES (3, 1, 'carType', '"hatchback"');
INSERT INTO test_table VALUES (3, 1, 'equipment', '["AT"]');
Upvotes: 1
Views: 90
Reputation: 121654
Use the function:
create or replace function jsonb_sort_array(jsonb)
returns jsonb language sql immutable as $$
select jsonb_agg(elem order by elem)
from jsonb_array_elements($1) elem
$$;
select *,
case jsonb_typeof(value_r)
when 'array' then jsonb_sort_array(value_r)
else value_r
end as sorted_value
from test_table;
id | ordinality | key_r | value_r | sorted_value
----+------------+-----------+--------------+--------------
1 | 1 | carType | "sedan" | "sedan"
1 | 1 | equipment | ["AT", "AC"] | ["AC", "AT"]
1 | 2 | extra | ["GPS"] | ["GPS"]
1 | 2 | carType | "hatchback" | "hatchback"
2 | 1 | carType | "sedan" | "sedan"
2 | 1 | equipment | ["BB", "AA"] | ["AA", "BB"]
3 | 1 | carType | "hatchback" | "hatchback"
3 | 1 | equipment | ["AT"] | ["AT"]
(8 rows)
Upvotes: 0