Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 87e8826

Browse files
authored
Create jsonb_unnest_recursive_distinct.sql
1 parent 0112591 commit 87e8826

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
create or replace function public.jsonb_unnest_recursive_distinct(data jsonb[])
2+
returns table(
3+
path text[],
4+
value jsonb,
5+
member_of text
6+
)
7+
immutable
8+
returns null on null input -- = strict
9+
parallel safe -- Postgres 10 or later
10+
security invoker
11+
language sql
12+
set search_path = ''
13+
as $func$
14+
--explain (analyse)
15+
with recursive r (path, value, member_of) as
16+
(
17+
select
18+
distinct --!!! also fix performance problem
19+
array[k.key],
20+
v.value,
21+
t.type
22+
from unnest(jsonb_unnest_recursive_distinct.data) as u(data)
23+
cross join jsonb_typeof(u.data) as t(type)
24+
left join jsonb_each(case t.type when 'object' then u.data end) as o(obj_key, obj_value) on true
25+
left join jsonb_array_elements(case t.type when 'array' then u.data end) with ordinality as a(arr_value, arr_key) on true
26+
cross join coalesce(o.obj_key, (a.arr_key - 1)::text) as k(key)
27+
cross join coalesce(o.obj_value, a.arr_value) as v(value)
28+
where t.type in ('object', 'array')
29+
and k.key is not null
30+
union --all
31+
select
32+
array_append(r.path, k.key),
33+
v.value,
34+
t.type
35+
from r
36+
cross join jsonb_typeof(r.value) as t(type)
37+
left join jsonb_each(case t.type when 'object' then r.value end) as o(obj_key, obj_value) on true
38+
left join jsonb_array_elements(case t.type when 'array' then r.value end) with ordinality as a(arr_value, arr_key) on true
39+
cross join coalesce(o.obj_key, (a.arr_key - 1)::text) as k(key)
40+
cross join coalesce(o.obj_value, a.arr_value) as v(value)
41+
where t.type in ('object', 'array')
42+
and k.key is not null
43+
)
44+
select r.*
45+
from r
46+
where jsonb_typeof(r.value) not in ('object', 'array');
47+
$func$;
48+
49+
comment on function public.jsonb_unnest_recursive_distinct(arr_data jsonb[])
50+
is 'Recursive parse nested JSONs (arrays and objects), returns distinct keys and its values';
51+
52+
------------------------------------------------------------------------------------------------------------------------
53+
--TEST
54+
55+
do $$
56+
begin
57+
assert (select count(*) = 9
58+
from public.jsonb_unnest_recursive_distinct(array[
59+
'{"id":123,"g":null,"a":[9,8,4,5],"name":"unknown", "7": 3}'::jsonb,
60+
'{"id":123,"g":null,"a":[9,8,4,5],"name":"unknown", "7": 3}'::jsonb,
61+
'{"id":123,"g":null,"a":[9,8,4,5],"name":"unknown", "7": 2}'::jsonb
62+
])
63+
);
64+
end;
65+
$$;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /