Unnest key value pairs from json object - mysql

I have a map with multiple key value pairs and I want to unnest them into separate rows.
"dayValueMap": {
"2022-06-01": 1,
"2022-06-02": 1,
"2022-06-03": 1,
"2022-06-04": 1,
"2022-06-05": 1,
"2022-06-06": 1,
}
I tried JSON_EXTRACT but that only extracts json from particular schema. Here I need to convert these key values as separate rows and in the map keys are dynamic.
Can someone help?

In MySQL 8.0 you can use:
JSON_KEYS: to extract the array of keys from "$.dayValueMap" path
JSON_TABLE: to generate a table containing your extracted keys, one per record
JSON_EXTRACT: to extract the value from your table, using the previously extracted keys
SELECT json_key,
JSON_EXTRACT(info, CONCAT('$.dayValueMap.', json_key)) AS json_value
FROM tab,
JSON_TABLE(
JSON_KEYS(info, '$.dayValueMap'), '$[*]'
COLUMNS(
json_key JSON PATH '$'
)
) t;
Check the demo here.

Related

oracle CLOB modify to obtain columns for json_table()

Since oracle does not support dynamic conversion of JSON column keys as relational column and JSON column value as relational column value, I had thought to generate my dynamic list of columns as CLOB column
col_a,col_b,col_c,col_d
and then convert it into below form
col_a NUMBER(22,3) PATH '$.col_a',col_b NUMBER(22,3) PATH '$.col_b',col_c NUMBER(22,3) PATH '$.col_c',col_d NUMBER(22,3) PATH '$.col_d'
Basically each of my column "col_a" is converted to "col_a NUMBER(22,3) PATH '$.col_a'"
so that I can directly place this clob value in my plsql block and fetch like below
select t.*,jt.*
from
table_1 t,
json_table(t.json_doc,'$' columns (col_a NUMBER(22,3) PATH '$.col_a',col_b NUMBER(22,3) PATH '$.col_b',col_c NUMBER(22,3) PATH '$.col_c',col_d NUMBER(22,3) PATH '$.col_d'))jt
but I'm not sure if i can do it using REPLACE or any other function.
I'm able to achieve it by concatenating while generating the original list of dynamic columns, but that additional burden I want to avoid.
NOTE: All columns are NUMBER(22,3) datatypes so not a burden on that side.
If your CLOB is valid JSON, you may be able to retrieve the keys for your CLOB using the function json_dataguide. Below is an example
My Table
create table json_doc (
data clob check (data is json)
);
insert into json_doc(data) values ('{"col1": "A"}');
insert into json_doc(data) values ('{"col2": "B"}');
Checking the table
select doc.data from json_doc doc;
-- DATA
-- 1 {"col1": "A"}
-- 2 {"col2": "B"}
Then using json_dataguide
select json_dataguide(doc.data) columns from json_doc doc;
-- COLUMNS
-- 1 [{"o:path":"$","type":"object","o:length":16},{"o:path":"$.col1","type":"string","o:length":1},{"o:path":"$.col2","type":"string","o:length":1}]
Finally, using json_table
select jt.* from
(select json_dataguide(doc.data) columns from json_doc doc) d,
json_table(d.columns, '$[*]' COLUMNS (
path varchar2(22) path '$."o:path"'
)) jt
-- PATH
-- 1 $
-- 2 $.col1
-- 3 $.col2
You can then get the JSON keys including the root (which you can easily remove as well as the $. in the beginning, perhaps using LTRIM).
If this solves your problem, remember to mark it as the answer ;)

MySql json reverse search

I have a MySQL table with a column of type json. The values of this columns are json array not json object. I need to find records of this table that at least one value of their json column is substring of the given string/phrase.
Let's suppose the table is looks like this:
create table if not exists test(id int, col json);
insert into test values (1, '["ab", "cd"]');
insert into test values (2, '["ef", "gh", "ij"]');
insert into test values (3, '["xyz"]');
If the input string/phrase is "acf ghi z" the second column must be returned as the result, because "gh" is a substring of the input. I read a lot about json_contains, json_extract, json_search and even json_overlaps but couldn't manage to solve this problem.
What is the correct sql syntax to retrieve the related rows?
MySQL version is 8.0.20
You can use json_table() to extract the JSON array as rows in a table. Then just filter:
select *
from test t cross join
json_table(t.col, '$[*]' columns (str varchar(255) path '$')) j
where 'acf ghi z' like concat('%', j.str, '%');
Here is a db<>fiddle.

Oracle reading JSON data using json_query

While working on oracle json datatype and trying to extract data from it, not able to extract name & value elements from this. tried using all known notations but getting null.
select json_query(po_document, '$.actions.parameters[0]') from j_purchaseorder where ID='2';
You can use the JSON_VALUE function as follows:
SQL> select JSON_VALUE('{"_class":"123", "name":"tejash","value":"so"}', '$.name') as name,
2 JSON_VALUE('{"_class":"123", "name":"tejash","value":"so"}', '$.value') as value
3 from dual;
NAME VALUE
---------- ----------
tejash so
SQL>
Thanks for your help. got required output using below
select json_value(json_query(po_document, '$.actions.parameters[0]'),'$.value') from j_purchaseorder where ID='2' and
json_value(json_query(po_document, '$.actions.parameters[0]'),'$.name') = 'SERVERUSER';
As explained, for example, in the Oracle documentation, multiple calls to JSON_VALUE() on the same JSON document may result in very poor performance. When we need to extract multiple values from a single document, it is often best (for performance) to make a single call to JSON_TABLE().
Here is how that would work on the provided document. First I create and populate the table, then I show the query and the output. Note the handling of column (attribute) "_class", both in the JSON document and in the SQL SELECT statement. In both cases the name must be enclosed in double-quotes, because it begins with an underscore.
create table j_purchaseorder (
id number primary key,
po_document clob check (po_document is json)
);
insert into j_purchaseorder (id, po_document) values (
2, '{"_class":"hudson.model.StringParameterValue","name":"SERVERUSER","value":"avlipwcnp04"}'
);
commit;
select "_CLASS", name, value
from j_purchaseorder
cross apply
json_table(po_document, '$'
columns (
"_CLASS" varchar2(40) path '$."_class"',
name varchar2(20) path '$.name',
value varchar2(20) path '$.value'
)
)
where id = 2
;
_CLASS NAME VALUE
---------------------------------------- ------------------ ------------------
hudson.model.StringParameterValue SERVERUSER avlipwcnp04

Extract value of single string record from PostgreSQL JSON column

For a given Postgres table:
CREATE TABLE "public"."store" (
"key" varchar(50) NOT NULL,
"value" json,
PRIMARY KEY ("key")
);
If I populate the following JSON encoded values:
INSERT INTO "store" VALUES ('integer', '1'),
('array', '{"foo": "bar"}'),
('string', '"baz"');
I can write a query to extract the value of foo like so:
SELECT value->>'foo' FROM store WHERE key = 'array'
And it returns the string value of bar (with no quotes).
However, I cannot figure it out is how should I write the query to get the unencoded value of the string key. The following query returns "baz" (with quotes).
SELECT value FROM store WHERE key = 'string'
How should I write this last query to extract the single string value of the 'string' key?
Use the #>> operator, from the docs: Get JSON object at specified path as text.
SELECT value #>>'{}' FROM store WHERE key = 'string'
Result: baz and not "baz".
EDIT:
You can also do the same when key = 'array':
SELECT value #>>'{foo}' FROM store WHERE key = 'array'

how to parse json using json_populate_recordset in postgres

I have a json stored as text in one of my database row. the json data is as following
[{"id":67272,"name":"EE_Quick_Changes_J_UTP.xlsx"},{"id":67273,"name":"16167.txt"},{"id":67274,"name":"EE_12_09_2013_Bcum_Searchall.png"}]
to parse this i want to use postgresql method
json_populate_recordset()
when I post a command like
select json_populate_recordset(null::json,'[{"id":67272,"name":"EE_Quick_Changes_J_UTP.xlsx"},{"id":67273,"name":"16167.txt"},{"id":67274,"name":"EE_12_09_2013_Bcum_Searchall.png"}]') from anoop;
it gives me following error
first argument of json_populate_recordset must be a row type
note : in the from clause "anoop" is the table name.
can anyone suggest me how to use the json_populate_recordset method to extract data from this json string.
I got method's reference from
http://www.postgresql.org/docs/9.3/static/functions-json.html
The first argument passed to pgsql function json_populate_recordsetshould be a row type. If you want to use the json array to populate the existing table anoop you can simply pass the table anoop as the row type like this:
insert into anoop
select * from json_populate_recordset(null::anoop,
'[{"id":67272,"name":"EE_Quick_Changes_J_UTP.xlsx"},
{"id":67273,"name":"16167.txt"},
{"id":67274,"name":"EE_12_09_2013_Bcum_Searchall.png"}]');
Here the null is the default value to insert into table columns not set in the json passed.
If you don't have an existing table, you need to create a row type to hold your json data (ie. column
names and their types) and pass it as the first parameter, like this anoop_type:
create TYPE anoop_type AS (id int, name varchar(100));
select * from json_populate_recordset(null :: anoop_type,
'[...]') --same as above
no need to create a new type for that.
select * from json_populate_recordset(null::record,'[{"id_item":1,"id_menu":"34"},{"id_item":2,"id_menu":"35"}]')
AS
(
id_item int
, id_menu int
)