2

This query not working, but the error not make sense

SELECT count(*) FROM t 
WHERE json_typeof(info->'vatids')='array' AND json_array_length(info->'vatids')>1;

ERROR: cannot get array length of a scalar

PS: idem with JSONb.

asked Mar 23, 2017 at 1:07
0

2 Answers 2

7

You didn't show us the data that is in that column nor did you show us the table definition. But I guess that you have something like this:

create table t (info json);
insert into t 
 (info)
values
 ('{"vatids" : ["one"]}'),
 ('{"vatids" : ["one", "two"]}'), 
 ('{"vatids" : "n/a"}');

There is no "short-circuit" of conditions in SQL, all conditions in the WHERE clause are applied (logically) at the same time, so json_array_length(info->'vatids') will fail for the third row even though you have json_typeof(info->'vatids')='array' as well.

The following will also not work, because the optimizer is smart enough to push the condition into the derived table:

select *
from (
 select info
 from t 
 where json_typeof(info->'vatids') = 'array' 
) x
where json_array_length(info->'vatids') > 1;

In this case you need a CTE that completely filters out the invalid rows, only then you can apply the condition on the array length:

with only_arrays as (
 select info
 from t 
 where json_typeof(info->'vatids') = 'array' 
)
select count(*)
from only_arrays
where json_array_length(info->'vatids') > 1;

This works because CTEs in Postgres act as an optimization fence and thus conditions from the outer query are not pushed into the CTE. Most of the times this is an disadvantage, but in this case it is indeed helpful.

answered Mar 23, 2017 at 8:38
1
  • legenday! Thank you so much Commented Oct 7, 2020 at 11:12
1

CTE doesn't seem to work anymore from version 15 of postgresql at least.

A solution could be :

select *
from (
 select case when jsonb_typeof(info->'vatids') = 'array' then 
 jsonb_array_length(info->'vatids') else 0 end as len, t.*
 from t ) x
 where len > 1;
answered Nov 13, 2023 at 10:10

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.