patternsqlMajor
Postgres function to merge two json objects with overlapping keys into one object
Viewed 0 times
postgresmergeobjectswithintofunctionkeystwooverlappingone
Problem
I've got the following JSON object:
I'd like to generate the following object and then be able to extract an element from it like so:
Extraction:
Basically, I have two arrays with potentially overlapping keys and I want to merge the two, giving one array precedence.
How can I accomplish this? Ideally I'd call a function like
{
"a" : {
"0" : 2,
"1" : 4,
"3" : 6,
},
"b" : {
"2" : 8,
"1" : 10, /*note this key exists in "a" too*/
"4" : 12,
}
}I'd like to generate the following object and then be able to extract an element from it like so:
{
"0" : 2,
"1" : 10,
"2" : 8,
"3" : 6,
"4" : 12,
}Extraction:
object->>'1' should return '10'Basically, I have two arrays with potentially overlapping keys and I want to merge the two, giving one array precedence.
How can I accomplish this? Ideally I'd call a function like
arrayMerge(a, b) and it gave 'a' higher precedence than 'b'Solution
If you're using PostgreSQL 9.5 (at least), you can use the concatenation operator (
For example:
will produce:
(Please note that, in this particular example, the parentheses around
You can modify the example above to get a specific value, as you requested, for example:
||) on jsonb types (and you can convert json to jsonb if necessary first).For example:
WITH test(data) AS (
VALUES ('{
"a" : {
"0" : 2,
"1" : 4,
"3" : 6
},
"b" : {
"2" : 8,
"1" : 10,
"4" : 12
}
}'::jsonb)
)
SELECT (data->'a') || (data->'b') FROM testwill produce:
{"0": 2, "1": 10, "2": 8, "3": 6, "4": 12}(Please note that, in this particular example, the parentheses around
(data->'a') matter.)You can modify the example above to get a specific value, as you requested, for example:
SELECT (((data->'a') || (data->'b'))->'1')::text::integer FROM testCode Snippets
WITH test(data) AS (
VALUES ('{
"a" : {
"0" : 2,
"1" : 4,
"3" : 6
},
"b" : {
"2" : 8,
"1" : 10,
"4" : 12
}
}'::jsonb)
)
SELECT (data->'a') || (data->'b') FROM test{"0": 2, "1": 10, "2": 8, "3": 6, "4": 12}SELECT (((data->'a') || (data->'b'))->'1')::text::integer FROM testContext
StackExchange Database Administrators Q#119089, answer score: 20
Revisions (0)
No revisions yet.