I have column "elements" in table which is having a json(array json) row values which looks like this
elements
[{"key":12,"value":"qw"},{"key":13,"value":"fa"}]
[{"key":32,"value":"24"},{"key":321,"value":"21"}]
I want to make an column of arrays for every row which consist of keys extracted from that row's json values ,my desired column "result" may look like this
elements
result
[{"key":12,"value":"qw"},{"key":13,"value":"fa"}]
{12,13}
[{"key":32,"value":"24"},{"key":321,"value":"21"}]
{32,321}
is there a way to do it? thank you
Schema (PostgreSQL v13)
CREATE TABLE test (
elements json
);
INSERT INTO test VALUES ('[{"key":12,"value":"qw"},{"key":13,"value":"fa"}]');
INSERT INTO test VALUES ('[{"key":32,"value":"24"},{"key":321,"value":"21"}]');
Query #1
select elements::text, array_agg(cast(value->>'key' as integer)) as result
from test, json_array_elements(elements)
group by 1
ORDER BY 1;
elements
result
[{"key":12,"value":"qw"},{"key":13,"value":"fa"}]
12,13
[{"key":32,"value":"24"},{"key":321,"value":"21"}]
32,321
View on DB Fiddle
select elements::text,
array_agg(value->>'key')
from your_table, json_array_elements(elements)
group by 1;
Related
I'm working with a subscriptions and plans tables. The subscriptions table has a product_quantity column and the plans table has a jsonb column called product_quantities_config that stores data in the following format {min: 0, step: 1, max: 10}.
Given the example above, would it be posible to transform the jsonb column data into an array of values starting from the min value up to the max value to end up with something like [0, 1, 2 .. 10] ?
I need to build a query to find all subscriptions where the product_quantity is not within the plans product_quantities_config boundaries, but I don't know how to transform the plans.product_quantity_config jsonb data into an array of values in Postgres (if it's even possible).
I suppose I'd then use that array of values as a subquery to find all subscriptions with a product_quantity NOT IN the given array of values.
You need to write a cross join statement to get a table of all values from jsonb, after which you can write a where product_quantity not in condition for the product table
select * from subscriptions where product_quantity not in (select value::int from plans cross join jsonb_each_text(product_quantities_config))
Demo in DBfiddle
I don't think you need to build an array.
It's unclear to me how the two table are related, but may something like this might do what you want:
select s.*
from subscriptions s
where not exists (select *
from plans
where s.product_quantity between (product_quantities_config ->> 'min')::int
and (product_quantities_config ->> 'max')::int)
One of my tables contains JSON values in each row of a column.
The data is as below (example. one row)
[{"id":"30a66bec-c0aa-4655-a8ef-506e52bfcc14","type":"nps","value":"promoter","decimalValue":"10"},{"id":"37850b3b-1eac-4921-ae22-b2f6d2450897","type":"sentiment","value":"positive","decimalValue":"0.990000009536743"}]
Now I'm trying to retrieve two columns from it. (id, value)
I'm writing the below query using JSON_VALUE but getting NULL values in each row of the new column.
select a.jsondata,JSON_VALUE(a.jsondata,'$.id') from table as a
Your JSON field is an array so you need to specify which element you're after, assuming its always the first you can use:
select a.jsondata,JSON_VALUE(a.jsondata,'$[0].id') from table as a
You need to change the index inside the square brackets to access the id you want from the JSON string
You have a JSON array. If you want to break it into multiple rows you need to use OPENJSON
SELECT j.*
FROM YourTable t
CROSS APPLY OPENJSON (t.Json)
WITH (
id uniqueidentifier,
value varchar(100)
) j;
db<>fiddle
I have coupule of columns in my table and one of them is a CLOB with json object.
I am working on data extraction mechanism from table and i was wondering if it is possible to create a new view with a new column containing certain value from that json (for example one column have rows with data like ...,"request":{"status":"open",.....} and i want new column STATUS)
Do you have any ideas how could I achieve this?
You can use JSON_VALUE.
SELECT
JSON_VALUE(jsonInfo,'$.request.status') status
FROM
( VALUES('{"request":{"status":"open"}}') ) J(jsonInfo)
Result:
status
------------
open
I have a table with PK and another column for other id. In some cases i need to insert record with equal values in both columns. For primary key values i'm using sequence, which gives a Field<Long> from Sequences.MY_SEQ.nextval().
How can i extract value from a Field<Long> for guaranteed insert same ids in both columns? Using Field<Long> in insert clause generates 2 different ids in columns.
Here is the solution:
Long id = dsl.select(Sequences.MY_SEQ.nextval()).fetchOne().value1();
Your own solution works, of course, but it will generate two round trips to the database. One for fetching the sequence value and another one for the insert. If that's not a problem, perfect. Otherwise, you can still do it in one single query using INSERT .. SELECT:
In SQL:
(using Oracle syntax. Your SQL syntax may vary...)
INSERT INTO my_table (col1, col2, val)
SELECT t.id, t.id, 'abc'
FROM (
SELECT my_seq.nextval AS id
FROM dual
) t
With jOOQ
Table<?> t = table(select(MY_SEQ.nextval().as("id"))).as("t");
dsl.insertInto(MY_TABLE)
.columns(MY_TABLE.COL1, MY_TABLE.COL2, MY_TABLE.VAL)
.select(
select(t.field("id"), t.field("id"), val("abc"))
.from(t))
.execute();
Is there a way to check if a value already exists in the hstore in the query itself.
I have to store various values per row ( each row is an "item").
I need to be able to check if the id already exists in database in one of the hstore rows without selecting everything first and doing loops etc in php.
hstore seems to be the only data type that offers something like that and also allows you to select the column for that row into an array.
Hstore may not be the best data type to store data like that but there isn't anything else better available.
The whole project uses 9.2 and i cannot change that - json is in 9.3.
The exist() function tests for the existence of a key. To determine whether the key '42' exists anywhere in the hstore . . .
select *
from (select test_id, exist(test_hs, '42') key_exists
from test) x
where key_exists = true;
test_id key_exists
--
2 t
The svals() function returns values as a set. You can query the result to determine whether a particular value exists.
select *
from (select test_id, svals(test_hs) vals
from test) x
where vals = 'Wibble';
hstore Operators and Functions
create table test (
test_id serial primary key,
test_hs hstore not null
);
insert into test (test_hs) values (hstore('a', 'b'));
insert into test (test_hs) values (hstore('42', 'Wibble'));