How to count setof / number of keys of JSON in pos

2020-08-10 09:26发布

I have a column in jsonb storing a map, like {'a':1,'b':2,'c':3} where the number of keys is different in each row.

I want to count it -- jsonb_object_keys can retrieve the keys but it is in setof

Are there something like this?

(select count(jsonb_object_keys(obj) from XXX )

(this won't work as ERROR: set-valued function called in context that cannot accept a set)

Postgres JSON Functions and Operators Document

json_object_keys(json)
jsonb_object_keys(jsonb)

setof text  Returns set of keys in the outermost JSON object.
json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')  

json_object_keys
------------------
f1
f2

Crosstab isn't feasible as the number of key could be large.

4条回答
在下西门庆
2楼-- · 2020-08-10 09:54

While a sub select must be used to convert the JSON keys set to rows, the following tweaked query might run faster by skipping building the temporary array:

SELECT count(*) FROM
   (SELECT jsonb_object_keys('{"a": 1, "b": 2, "c": 3}'::jsonb)) v;

and it's a bit shorter ;)

To make it a function:

CREATE OR REPLACE FUNCTION public.count_jsonb_keys(j jsonb)
  RETURNS bigint
  LANGUAGE sql
AS $function$
SELECT count(*) from (SELECT jsonb_object_keys(j)) v;
$function$
查看更多
不美不萌又怎样
3楼-- · 2020-08-10 09:54

Alternately, you could simply return the upper bounds of the keys when listed as an array:

SELECT
    ARRAY_UPPER( -- Grab the upper bounds of the array
        ARRAY( -- Convert rows into an array.
            SELECT JSONB_OBJECT_KEYS(obj)
        ),
        1 -- The array's dimension we're interested in retrieving the count for
    ) AS count
FROM
    xxx

Using '{"a": 1, "b": 2, "c": 3}'::jsonb as obj, count would result in a value of three (3).

Pasteable example:

SELECT
    ARRAY_UPPER( -- Grab the upper bounds of the array
        ARRAY( -- Convert rows into an array.
             SELECT JSONB_OBJECT_KEYS('{"a": 1, "b": 2, "c": 3}'::jsonb)
        ),
        1 -- The array's dimension we're interested in retrieving the count for
    ) AS count
查看更多
可以哭但决不认输i
4楼-- · 2020-08-10 09:58

You could convert keys to array and use array_length to get this:

select array_length(array_agg(A.key), 1) from (
    select json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}') as key
) A;

If you need to get this for the whole table, you can just group by primary key.

查看更多
老娘就宠你
5楼-- · 2020-08-10 10:05

Shortest:

SELECT count(*) FROM jsonb_object_keys('{"a": 1, "b": 2, "c": 3}'::jsonb);

Returns 3

If you want all json number of keys from a table, it gives:

SELECT (SELECT COUNT(*) FROM json_object_keys(myJsonField)) nbr_keys FROM myTable;
查看更多
登录 后发表回答