5

As known, in Postgres json, we can get one element at a specified index from an array using this:

["a","b","c"]::json -> 2

The script above return the 3rd element "c".

Then is there any way a range of elements can be returned if I specify a index range such as 0 to 20?

1
  • Thank all of you guys, all your answers are helpful at all. Furthermore, the element amount of my array in practice is over 20000, would anyone tell me which way best performance, tks. Commented Nov 2, 2016 at 10:41

4 Answers 4

6

In PostgreSQL 12, I managed to engineer JSONB array slice using the jsonb_path_query_array function as follows:

SELECT jsonb_path_query_array('["a","b","c","d","e","f"]', '$[2 to 4]');
 jsonb_path_query_array
------------------------
 ["c", "d", "e"]
(1 row)
Sign up to request clarification or add additional context in comments.

Comments

4

You can convert the json array to a real array by changing the text representation from '["a","b","c"]' to '{"a","b","c"}' and cast the result to text[].

Then you can use the usual Postgres array subscript:

select (translate('["a","b","c"]'::json::text, '[]','{}')::text[])[1:2]

returns

{a,b}

Note that native Postgres arrays are one-based (first element has the index 1), unlike the JSON arrays which are zero-based.

Comments

3

With json_array_elements and row_number for example:

db=> select value
     from (select row_number() over (), value
           from json_array_elements('["a","b","c"]'::json)
     ) as t
     where row_number between 2 and 3;
 value 
-------
 "b"
 "c"
(2 rows)

or by using WITH ORDINALITY

db=> select value
     from json_array_elements('["a","b","c"]'::json)
     with ordinality
     where ordinality between 2 and 3;
 value 
-------
 "b"
 "c"
(2 rows)

5 Comments

Would you tell me which way better performance?My array is very large.
@YinAqu with ordinality shold be faster (no explicit joins to get a row number)
Tks, would u plz check this sql for me, the sub query is fault grammar. select value from json_array_elements(select result_json from hfj_search where search_uuid='16aa6bd4-0b8b-403b-b165-efaab863bf7e') with ordinality where ordinality between 2 and 3;
@YinAqu try with additional parentheses to subquery: select value from json_array_elements( (subquery in parentheses) ) with ordinality where ordinality between 2 and 3;
Require explicit type conversion, this works: select value from json_array_elements( (subquery in parentheses)::json ) with ordinality where ordinality between 2 and 3;
1

You can create your own function (as there is no such a feature in Postgres):

create or replace function json_sub_array(json_array json, from_pos int, to_pos int)
returns json language sql as $$
    select json_agg(value)
    from json_array_elements(json_array) with ordinality
    where ordinality-1 between from_pos and to_pos
$$;

select json_sub_array('["a","b","c","d"]'::json, 1, 2);

 json_sub_array 
----------------
 ["b", "c"]
(1 row) 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.