Extract sub JSON with keys and values in MYSQL - 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';

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

POSTGRESQL copy jsonb value to new column

I want extract a json value from a column and insert it into a new one.
Example row as an insert statement copied:
INSERT INTO "table_name".("booking_number","arrival_date","departure_date","custom_fields","customer_id","import_id","id","at_table","a_la_carte","value")
VALUES
(E'00000007',E'2019-01-02 12:00:00',E'2020-02-05 12:00:00',E'[{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}, {"value": "3/3/3/3/3", "display_name": "Personen Anzahl", "servicio_tags": ["person-number-info"]}, {"value": "en", "display_name": "Sprache", "servicio_tags": ["language"]}, {"value": " Robotics", "display_name": "Begleiter", "servicio_tags": ["accompanied-guests"]}, {"value": "2. Januar 2019", "display_name": "Anreise", "servicio_tags": ["arrival"]}, {"value": "5. Februar 2020", "display_name": "Abreise", "servicio_tags": ["departure"]}, {"value": "EBROV RO", "display_name": "Rate Code", "servicio_tags": ["price-type"]}, {"value": "SSV", "display_name": "Zimmer Typ", "servicio_tags": ["room-type"]}, {"value": "2013", "display_name": "Zimmernummer", "servicio_tags": ["room-number"]}, {"value": "Australia", "display_name": "Nation", "servicio_tags": ["nation"]}, {"value": "", "display_name": "Gruppe", "servicio_tags": ["group-name"]}]',1,36020,369528,FALSE,FALSE,E'{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}');
I want to extract the protelUniqueID with the servicio-tag ["protel-info"]. In the best case only the ID value. In this case 294623726.
Then I want to create a new column named guest_profile_id in this table named guest_group and insert this value in for the same row.
So I think this needs to be done by the following steps:
Creating new column
Query id from json column
Insert id to new column
My try so far for step 2)
SELECT *
 FROM guest_group gg
cross join lateral jsonb_array_elements(custom_fields) 
WHERE value #> '{"servicio_tags": ["protel-info"]}'::jsonb
AND gg.customer_id = 1
Thanks for the help.
First of all protelUniqueID is a list. You need the only first ID from a list as I understood.
Note! "protelUniqueID": "[{\\"ID\\": .... looks like strange format. Is like json as string inside json. Anyway I share solution for your description.
CREATE TABLE my_tbl (custom_fields jsonb);
INSERT INTO my_tbl (custom_fields)
VALUES
(
E'{"protelSurname": "Smith", "servicio_tags": ["protel-info"], "protelUniqueID": "[{\\"ID\\":\\"294623726\\",\\"Type\\":\\"21\\",\\"ID_Context\\":\\"GHA\\"},{\\"ID\\":\\"4842148\\",\\"Type\\":\\"1\\",\\"ID_Context\\":\\"protelIO\\"}]", "protelGivenName": "Seth"}'
);
Let's try to select our ID(294623726):
SELECT
custom_fields::json->'servicio_tags' AS tags,
CAST(CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>0 AS jsonb)->>'ID' AS protel_first_id
FROM my_tbl;
-- tags,protel_first_id
--["protel-info"],294623726
All what we need is just add a column + update
ALTER TABLE my_tbl ADD COLUMN guest_profile_id INTEGER DEFAULT NULL;
UPDATE my_tbl set guest_profile_id = CAST(CAST(CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>0 AS jsonb)->>'ID' AS INTEGER) WHERE guest_profile_id IS NULL;
db-fiddle example
Note! You can remove 1 CAST if you'll use clear format:
INSERT INTO my_tbl (custom_fields)
VALUES
(
E'{"protelUniqueID": [{"ID":"294623726","Type":"21","ID_Context":"GHA"},{"ID":"4842148","Type":"1","ID_Context":"protelIO"}]}'
);
SELECT
CAST(CAST(custom_fields::json->'protelUniqueID' AS jsonb)->>0 AS jsonb)->>'ID' AS protel_first_id
FROM my_tbl;
Hope this helps.

PostgreSQL query : distinct count of jsonb values column

I have a table with the name mainapp_project_data which has a jsonb column project_user_data
TABLE
public | mainapp_project_data | table | admin
select project_user_data from mainapp_project_data;
project_user_data
-----------------------------------------------------------------------------------------------------------------
[{"name": "john", "age": "21", "gender": "M"}, {"name": "randy", "age": "23", "gender": "M"}]
[{"name": "donald", "age": "31", "gender": "M"}, {"name": "wick", "age": "32",
"gender": "M"}]
[{"name": "orton", "age": "18", "gender": "M"}, {"name": "russel", "age": "55",
"gender": "M"}]
[{"name": "angelina", "age": "open", "gender": "F"}, {"name": "josep", "age": "21",
"gender": "M"}]
(4 rows)
(END)
I would like to count the distinct values of keys gender and age of JSON.
output format : [{key:count(repeated_values)}]
filtering on `gender` : [{"M":7},{"F":1}]
filtering on `age` : [{"21":2},{"23":1},{"31":1}.....]
WITH flat AS (
SELECT
kv.key,
-- make into a JSON object with a single value and count, e.g., '{"M": 7}'
jsonb_build_object(kv.value, COUNT(*)) AS val_count
FROM mainapp_project_data AS mpd
-- Flatten the JSON arrays into single objects per row
CROSS JOIN LATERAL jsonb_array_elements(mpd.project_user_data) AS unarrayed(udata)
-- Convert to a long, flat list of key-value pairs
CROSS JOIN LATERAL jsonb_each_text(unarrayed.udata) AS kv(key, value)
GROUP BY kv.key, kv.value
)
SELECT
-- de-deplicated object keys
flat.key,
-- aggregation of all values and counts per key
jsonb_agg(flat.val_count) AS value_counts
FROM flat
GROUP BY flat.key
Returns
key | value_counts
--------+---------------------------------------------------------------------------------------------------------------------
gender | [{"M": 7}, {"F": 1}]
name | [{"josep": 1}, {"russel": 1}, {"orton": 1}, {"donald": 1}, {"wick": 1}, {"john": 1}, {"randy": 1}, {"angelina": 1}]
age | [{"18": 1}, {"32": 1}, {"21": 2}, {"23": 1}, {"open": 1}, {"31": 1}, {"55": 1}]
This will provide any key-value pair instance count. If you just want genders and ages, just add a where clause before the first GROUP BY clause.
WHERE kv.key IN ('gender', 'age')
Does something like this work for you?
postgres=# select count(*), (foo->'gender')::text as g from (select json_array_elements(project_user_data) as foo from mainapp_project_data) as j group by (foo->'gender')::text;
count | g
-------+-----
7 | "M"
1 | "F"
(2 rows)
postgres=# select count(*), (foo->'age')::text as g from (select json_array_elements(project_user_data) as foo from mainapp_project_data) as j group by (foo->'age')::text;
count | g
-------+--------
2 | "21"
1 | "32"
1 | "open"
1 | "23"
1 | "18"
1 | "55"
1 | "31"
(7 rows) ```

How to query nested array of jsonb

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

How can I extract all values of a particular attribute within elements inside a JSON array in MySQL?

I've the below data stored in a column of MySQL table which is of "json" data type (MySQL v5.7.9)
[{"id": "26", "title": "similar1", "score": "0.97"}, {"id": "27", "title": "similar2", "score": "0.87"}, {"id": "28", "title": "similar2", "score": "0.87"}]
I need a MySQL query which will return me all the "title" values i.e. similar1, similar2 and similar3 and so on
Use JSON_EXTRACT().
mysql> create table t ( j json );
mysql> insert into t set j = '[{"id": "26", "title": "similar1", "score": "0.97"}, {"id": "27", "title": "similar2", "score": "0.87"}, {"id": "28", "title": "similar2", "score": "0.87"}]';
mysql> select json_extract(j, '$[*].title') from t;
+--------------------------------------+
| json_extract(j, '$[*].title') |
+--------------------------------------+
| ["similar1", "similar2", "similar2"] |
+--------------------------------------+
If you want to use JSON data in MySQL, you should read the docs on Functions that Search JSON Values, and learn to use the JSON search expressions.
This looks like a database design issue. It seems that you're using a json column when you should really be using another table to store these results as individual columns.
you can query like below
create table testTableforus (datapoint json);
insert into testTableforus
values
('{"id": "26", "title": "similar1", "score": "0.97"}'),
('{"id": "27", "title": "similar2", "score": "0.87"}'),
('{"id": "28", "title": "similar2", "score": "0.87"}');
select datapoint->"$.title" from testTableforus;
drop table testTableforus;
See working demo