To quickly test some SQL — say, how to query our payment_requests table for how many failed attempts each request had — I used to connect to a playground database in my local instance and run something like this:

-- create simple version of the actual table
create table payment_requests (
    attempts jsonb
);

-- insert test data
-- each array entry is a request attempt
insert into payment_requests values
('[{"status": "FAILED"}]'::jsonb),
('[{"status": "FAILED"}, {"status": "FAILED"}]'),
('[{"status": "FAILED"}, {"status": "DECLINED"}]'),
('[{"status": "DECLINED"}, {"status": "FAILED"}, {"status": "FAILED"}]'),
('[{"status": "FAILED"}, {"status": "DECLINED"}, {"status": "FAILED"}]');

-- hack my way to a working query
select
    (
        select count(*)
        from jsonb_array_elements(attempts) as attempt
        where attempt ->> 'status' = 'FAILED'
    ) as num_failures,
    count(*)
from payment_requests
group by num_failures;

This approach gets the job done, but has some annoying features.

There must be a better way!

How about this?

with payment_requests (attempts) as (
    values
    ('[{"status": "FAILED"}]'::jsonb),
    ('[{"status": "FAILED"}, {"status": "FAILED"}]'),
    ('[{"status": "FAILED"}, {"status": "DECLINED"}]'),
    ('[{"status": "DECLINED"}, {"status": "FAILED"}, {"status": "FAILED"}]'),
    ('[{"status": "FAILED"}, {"status": "DECLINED"}, {"status": "FAILED"}]')
)

select
    (
        select count(*)
        from jsonb_array_elements(attempts) as attempt
        where attempt ->> 'status' = 'FAILED'
    ) as num_failures,
    count(*)
from payment_requests
group by num_failures;

I had assumed that values could only be used as part of an insert. Not so: it’s a command in its own right, which can be used to hard-code a table without writing to disk. For example,

values (1, 'one'), (2, 'two'), (3, 'three');

is valid SQL, "effectively equivalent", say the docs, to

select 1 as column1, 'one' as column2
union all
select 2, 'two'
union all
select 3, 'three';

This with-values-select approach avoids the annoying features of create-insert-select above.

So: with-values-select beats create-insert-select.