How to query nested array of jsonb - json

I am working on a PostgreSQL 11 table with a column of nested and multiple jsonb objects
to simulate the issue: -
CREATE TABLE public.test
(
id integer NOT NULL DEFAULT nextval('test_id_seq'::regclass),
testcol jsonb
)
insert into test (testcol) values
('[{"type": {"value": 1, "displayName": "flag1"}, "value": "10"},
{"type": {"value": 2, "displayName": "flag2"}, "value": "20"},
{"type": {"value": 3, "displayName": "flag3"}, "value": "30"},
{"type": {"value": 4, "displayName": "flag4"}},
{"type": {"value": 4, "displayName": "flag4"}},
{"type": {"value": 6, "displayName": "flag6"}, "value": "40"}]');
I am trying to:
get outer value if type= specific value. e.g. get the value 30, if flag3 is in displayname.
count occurrence of flag4 in inner json

You could use json_to_recordset to parse it:
WITH cte AS (
SELECT test.id, sub."type"->'value' AS t_value, sub."type"->'displayName' AS t_name, value
FROM test
,LATERAL jsonb_to_recordset(testcol) sub("type" jsonb, "value" int)
)
SELECT *
FROM cte
-- WHERE ...
-- GROUP BY ...;
db<>fiddle demo

Related

How to get array/object number value in postgreSQL?

Is it possible to get array/object number values.
I have a table called tableA:
create table "tableA" (
"_id" serial,
"userId" integer,
"dependentData" jsonb);
INSERT INTO "tableA"
("_id", "userId", "dependentData")
VALUES('55555', '1191', '[{"_id": 133, "type": "radio", "title": "questionTest7", "question": "questionTest7", "response": {"value": ["option_11"]}, "dependentQuestionResponse": [{"_id": 278, "type": "text", "title": "questionTest8", "question": "questionTest8", "response": {"value": ["street no 140"]}, "dependentQuestionResponse": []}]}, {"_id": 154, "type": "dropdown", "title": "questionTest8", "question": "questionTest8", "response": {"value": ["option_14"]}, "dependentQuestionResponse": []}]');
Array number is to be fetched. Output should be require below.
_id
userId
array/object
55555
1191
[0,0,1]
You can try something like this
select id, user_id,
(
with
base as (
select o1, oo1.a oo1 from (
select jsonb_array_elements(t.a) o1
from (select depend_data as a) t
) o
left join lateral (select a from jsonb_array_elements(o.o1-> 'dependentQuestionResponse') a) oo1 on true
)
select json_agg(nn) from (
select dense_rank() over(order by b.o1) - 1 nn, b.o1 from base b
union all
select dense_rank() over(order by b.o1) - 1 nn, b.oo1 from base b where oo1 is not null
order by nn
) tz
) as array_object
from
(select 55555 as id,
1191 as user_id,
'[{"_id": 133, "type": "radio", "title": "questionTest7", "question": "questionTest7", "response": {"value": ["option_11"]}, "dependentQuestionResponse": [
{"_id": 278, "type": "text", "title": "questionTest8", "question": "questionTest8", "response": {"value": ["street no 140"]},"dependentQuestionResponse": []}]},
{"_id": 154, "type": "dropdown", "title": "questionTest8", "question": "questionTest8", "response": {"value": ["option_14"]}, "dependentQuestionResponse": []}]'::jsonb as depend_data) t

Extract sub JSON with keys and values in MYSQL

I have a table with a JSON TYPE column like this:
id
json_info
date
1.
{"Ccclaptop_model": {"value": "asus", "price": "2122"}, "laptop_ram": {"value": "6", "price": "122"}, "laptop_mouse_model": {"value": "logic", "price": "30"} , "laptop_keys_model": {"value": "USA", "price": "10"}}
2020-02-02
And I'd like to have a query that extracts a sub-JSON with his key value, like this:
id
json_info
date
1.
{"laptop_mouse_model": {"value": "logic", "price": "30"} , "laptop_keys_model": {"value": "USA", "price": "10"}}
2020-02-02
I have tried JSON_EXTRACT
SELECT id,
JSON_EXTRACT(json_info, '$.laptop_mouse_model', '$.laptop_keys_model' ) AS store_id
FROM feature_data WHERE date = '2020-02-02';
but just return a JSON array without keys, like this:
id
json_info
date
1.
[{"value": "logic", "price": "30"} ,{"value": "USA", "price": "10"}]
2020-02-02
Does somebody know if exists a function that I could use?
You can use JSON_OBJECT to combine result to a json, for example:
SELECT id,JSON_OBJECT('laptop_mouse_model',JSON_EXTRACT(json_info, '$.laptop_mouse_model'),'laptop_keys_model',JSON_EXTRACT(json_info, '$.laptop_keys_model')) AS store_id FROM feature_data WHERE date = '2020-02-02';

How do you use JSON_QUERY with null json array inside of json object?

SELECT JSON_query([json], '$') from mytable
Returns fine the contents of [json] field
SELECT JSON_query([json], '$.Guid') from mytable
Returns null
SELECT JSON_query([json], '$.Guid[1]') from mytable
Returns null
I've also now tried:
SELECT JSON_query([json], '$[1].Guid')
SELECT JSON_query([json], '$[2].Guid')
SELECT JSON_query([json], '$[3].Guid')
SELECT JSON_query([json], '$[4].Guid')
and they all return null
So I'm stuck as to figuring out how create the path to get to the info. Maybe SQL Server json_query can't handle the null as the first array?
Below is the string that is stored inside of the [json] field in the database.
[
null,
{
"Round": 1,
"Guid": "15f4fe9d-403c-4820-8e35-8a8c8d78c33b",
"Team": "2",
"PlayerNumber": "78"
},
{
"Round": 1,
"Guid": "8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67",
"Team": "2",
"PlayerNumber": "54"
},
{
"Round": 1,
"Guid": "f53cd74b-ed5f-47b3-aab5-2f3790f3cd34",
"Team": "1",
"PlayerNumber": "23"
},
{
"Round": 1,
"Guid": "30297678-f2cf-4b95-a789-a25947a4d4e6",
"Team": "1",
"PlayerNumber": "11"
}
]
You need to follow the comments below your question. I'll just summarize them:
Probably the most appropriate approach in your case is to use OPENJSON() with explicit schema (the WITH clause).
JSON_QUERY() extracts a JSON object or a JSON array from a JSON string and returns NULL. If the path points to a scalar JSON value, the function returns NULL in lax mode and an error in strictmode. The stored JSON doesn't have a $.Guid key, so NULL is the actual result from the SELECT JSON_query([json], '$.Guid') FROM mytable statement.
The following statements provide a working solution to your problem:
Table:
SELECT *
INTO Data
FROM (VALUES
(N'[
null,
{
"Round": 1,
"Guid": "15f4fe9d-403c-4820-8e35-8a8c8d78c33b",
"Team": "2",
"PlayerNumber": "78",
"TheProblem": "doesn''t"
},
{
"Round": 1,
"Guid": "8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67",
"Team": "2",
"PlayerNumber": "54"
},
{
"Round": 1,
"Guid": "f53cd74b-ed5f-47b3-aab5-2f3790f3cd34",
"Team": "1",
"PlayerNumber": "23"
},
{
"Round": 1,
"Guid": "30297678-f2cf-4b95-a789-a25947a4d4e6",
"Team": "1",
"PlayerNumber": "11"
}
]')
) v (Json)
Statements:
SELECT j.Guid
FROM Data d
OUTER APPLY OPENJSON(d.Json) WITH (
Guid uniqueidentifier '$.Guid',
Round int '$.Round',
Team nvarchar(1) '$.Team',
PlayerNumber nvarchar(2) '$.PlayerNumber'
) j
SELECT JSON_VALUE(j.[value], '$.Guid')
FROM Data d
OUTER APPLY OPENJSON(d.Json) j
Result:
Guid
------------------------------------
15f4fe9d-403c-4820-8e35-8a8c8d78c33b
8e91596b-cc33-4ce7-bfc0-ac3d1dc5eb67
f53cd74b-ed5f-47b3-aab5-2f3790f3cd34
30297678-f2cf-4b95-a789-a25947a4d4e6

Select certain keys from array of objects

Say I have a JSON column foo where each value is an array of objects, i.e:
[{"date": somedate, "value": somevalue, "othervaluesidontneed":...},
{"date": somedate, "value": somevalue, "othervaluesidontneed":...},
{"date": somedate, "value": somevalue, "othervaluesidontneed":...},...]
I want to select this column but for each row, to only include the keys date and value, so the returned value is:
[{"date": somedate, "value": somevalue},
{"date": somedate, "value": somevalue},
{"date": somedate, "value": somevalue},...]
Is this possible?
A solution would be to use json_table() (available in MySQ 8.0 only) to expand the array as a set of rows, and then generate a new array of objects that contain only the requested keys with json_arrayagg():
select
json_arrayagg(json_object( 'date', tt.date, 'value', tt.value)) new_js
from
mytable t,
json_table(
js,
"$[*]"
columns(
date datetime path "$.date",
value int path "$.value"
)
) as tt
group by t.id
This requires that some column can be used to uniquely identify a row in the initial table: I called that column id.
Demo on DB Fiddle:
with mytable as (
select 1 id, '[
{ "date": "2019-01-01", "value": 1, "othervaluesidontneed": 12 },
{ "date": "2019-01-02", "value": 2, "othervaluesidontneed": 55 },
{ "date": "2019-01-03", "value": 3, "othervaluesidontneed": 72}
]' js
)
select
json_arrayagg(json_object( 'date', tt.date, 'value', tt.value)) new_js
from
mytable t,
json_table(
js,
"$[*]"
columns(
date datetime path "$.date",
value int path "$.value"
)
) as tt
group by t.id
| new_js |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [{"date": "2019-01-01 00:00:00.000000", "value": 1}, {"date": "2019-01-02 00:00:00.000000", "value": 2}, {"date": "2019-01-03 00:00:00.000000", "value": 3}] |

Find rows by multiple keys and values from json column in postgres

I have a table which has a json column and I want to get only the rows that has an specific key an value into the json like this:
here is the an example of the value from that column when I do a simple select query like:
select my_atribute from displays;
result:
{"key": "unit_type", "value": "Tablet", "display_name": "Unit Type"}
{"key": "pack_type", "value": "Packet", "display_name": "Pack Type"}
{"key": "units_in_pack", "value": "60", "display_name": "Units in Pack"}
{"key": "item_unit", "value": "", "display_name": "Item unit"}
{"key": "item_size", "value": "1", "display_name": "Item Size"}
{"key": "details", "value": "", "display_name": "Details"}
{"key": "slug", "value": "otc7087", "display_name": "Slug"}
I want only the rows that have "key" like "slug"or "details" and "display_name" like "Item unit" or "Details"
I've tried the code bellow:
WITH my_table(jsonblob) AS (VALUES ((select my_atribute from displays) :: jsonb))
SELECT elem ->> 'value'
FROM my_table
CROSS JOIN LATERAL jsonb_array_elements(jsonblob) elem
WHERE ((elem ->> 'key') in ('slug', 'details'))
and ((elem ->> 'display_name') in ('Item unit', 'Details'));
and here is the message that I get:
ERROR: more than one row returned by a subquery used as an expression