PLSQL: remove unwanted double quotes in a Json - sql

I have a Json like this (it is contained in a clob variable):
{"id": "33", "type": "abc", "val": "2", "cod": "", "sg1": "1", "sg2": "1"}
{"id": "359", "type": "abcef", "val": "52", "cod": "aa", "sg1": "", "sg2": "0"}
…
I need to remove " from values of: id, val, sg1, sg2
Is it possibile?
For example, I need to obtain this:
{"id": 33, "type": "abc", "val": 2, "cod": "", "sg1": 1, "sg2": 1}
{"id": 359, "type": "abcef", "val": 52, "cod": "aa", "sg1": , "sg2": 0}
…

If you are using Oracle 12 (R2?) or later then you can convert your JSON to the appropriate data types and then convert it back to JSON.
Oracle 18 Setup:
CREATE TABLE test_data ( value CLOB );
INSERT INTO test_data ( value )
VALUES ( '{"id": "33", "type": "abc", "val": "2", "cod": "", "sg1": "1", "sg2": "1"}' );
INSERT INTO test_data ( value )
VALUES ( '{"id": "359", "type": "abcef", "val": "52", "cod": "aa", "sg1": "", "sg2": "0"}' );
Query:
SELECT JSON_OBJECT(
'id' IS j.id,
'type' IS j.typ,
'val' IS j.val,
'cod' IS j.cod,
'sg1' IS j.sg1,
'sg2' IS j.sg2
) AS JSON
FROM test_data t
CROSS JOIN
JSON_TABLE(
t.value,
'$'
COLUMNS
id NUMBER(5,0) PATH '$.id',
typ VARCHAR2(10) PATH '$.type',
val NUMBER(5,0) PATH '$.val',
cod VARCHAR2(10) PATH '$.cod',
sg1 NUMBER(5,0) PATH '$.sg1',
sg2 NUMBER(5,0) PATH '$.sg2'
) j
Output:
| JSON |
| :--------------------------------------------------------------- |
| {"id":33,"type":"abc","val":2,"cod":null,"sg1":1,"sg2":1} |
| {"id":359,"type":"abcef","val":52,"cod":"aa","sg1":null,"sg2":0} |
Or, if you want to use regular expressions (you shouldn't if you have the choice and should use a proper JSON parser instead) then:
Query 2:
SELECT REGEXP_REPLACE(
REGEXP_REPLACE(
value,
'"(id|val|sg1|sg2)": ""',
'"\1": "null"'
),
'"(id|val|sg1|sg2)": "(\d+|null)"',
'"\1": \2'
) AS JSON
FROM test_data
Output:
| JSON |
| :-------------------------------------------------------------------------- |
| {"id": 33, "type": "abc", "val": 2, "cod": "", "sg1": 1, "sg2": 1} |
| {"id": 359, "type": "abcef", "val": 52, "cod": "aa", "sg1": null, "sg2": 0} |
db<>fiddle here

Related

Query a single element from a dictionary-like column in SQL

I have a PostgresSQL table that looks as follows:
id order_id products
[PK] integer integer character varying
1 123 {"type": "foo", "counts": 2}
2 456 {"type": "foobar", "counts": 4}
3 789 {"type": "foo", "counts": 1}
4 678 {"type": "baz", "counts": 3}
I would like to query for only where type = foo.
In another query, I've successfully used the following:
SELECT
table_a.data::json->>'type' prod_type,
FROM table.a
But, this only works because the data column is JSON type.
How would I index into the products column such that I only return type = foo?
1 123 {"type": "foo", "counts": 2}
3 789 {"type": "foo", "counts": 1}
Thanks!
You can try something like this:
SELECT *
FROM test
WHERE products::json->>'type' = 'foo';
Sample Output:

Kusto Query JSON Array Values

can anyone offer a clue on how to do query values within arrays -- such as below, I want to find all records where
DiscoveredInformationTypes_s Confidence > 80
Can anyone help? How do I query inside this array?
MachineName_s
Version_s
ProcessName_s
ApplicationName_s
Operation_s
ObjectId_s
DiscoveredInformationTypes_s
[ { "Confidence": 55, "Count": 1, "SensitiveType": "3356946c-6bb7-449b-b253-6ffa419c0ce7", "UniqueCount": 1, "SensitiveInformationDetections": null, "Name": "International Classification of Diseases (ICD-10-CM)" } ]
you can use mv-apply: https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/mv-applyoperator
for example:
datatable(DiscoveredInformationTypes_s:dynamic)
[
dynamic([ { "Confidence": 55, "Count": 1, "SensitiveType": "3356946c-6bb7-449b-b253-6ffa419c0ce7", "UniqueCount": 1, "SensitiveInformationDetections": null, "Name": "International Classification of Diseases (ICD-10-CM)" } ]),
dynamic([ { "Confidence": 81, "Count": 1, "SensitiveType": "3356946c-6bb7-449b-b253-6ffa419c0ce7", "UniqueCount": 1, "SensitiveInformationDetections": null, "Name": "International Classification of Diseases (ICD-10-CM)" } ])
]
| mv-apply DiscoveredInformationTypes_s on (
where DiscoveredInformationTypes_s.Confidence > 80
)
or, if your column is string-typed and not dynamic-typed, you'll need to invoke parse_json() on it first:
datatable(s:string)
[
'[ { "Confidence": 55, "Count": 1, "SensitiveType": "3356946c-6bb7-449b-b253-6ffa419c0ce7", "UniqueCount": 1, "SensitiveInformationDetections": null, "Name": "International Classification of Diseases (ICD-10-CM)" } ]',
'[ { "Confidence": 81, "Count": 1, "SensitiveType": "3356946c-6bb7-449b-b253-6ffa419c0ce7", "UniqueCount": 1, "SensitiveInformationDetections": null, "Name": "International Classification of Diseases (ICD-10-CM)" } ]'
]
| project DiscoveredInformationTypes_s = parse_json(s)
| mv-apply DiscoveredInformationTypes_s on (
where DiscoveredInformationTypes_s.Confidence > 80
)

How to build rows of JSON from a table with one one-to-many relationship

I have a table main like this:
create foreign table main (
"id" character varying not null,
"a" character varying not null,
"b" character varying not null
)
And I have another table, not_main, like this:
create foreign table not_main (
"id" character varying not null,
"fk" character varying not null,
"d" character varying not null,
"e" character varying not null
)
Should I want a query whose return is like:
json
0 {"id": "id_main_0", "a": "a0", "b": "b0", "cs": [{"id": "id_not_main_0", "fk": "id_main_0", "d": "d0", "e": "e0"}, {"id": "id_not_main_1", "fk": "id_main_0", "d": "d1", "e": "e1"}]}
1 {"id": "id_main_1", "a": "a1", "b": "b1", "cs": [{"id": "id_not_main_2", "fk": "id_main_1", "d": "d2", "e": "e3"}, {"id": "id_not_main_3", "fk": "id_main_1", "d": "d3", "e": "e3"}]}
How should I do it?
I tried:
select
json_build_object(
'id', m."id",
'a', m."a",
'b', m."b",
'cs', json_build_array(
json_build_object(
'd', nm."d",
'e', nm."e"
)
)
)
from main m
left join not_main nm on
nm."requisitionId" = m.id;
But it returns only one element in cs:
json
0 {"id": "id_main_0", "a": "a0", "b": "b0", "cs": [{"id": "id_not_main_0", "fk": "id_main_0", "d": "d0", "e": "e0"}]}
1 {"id": "id_main_1", "a": "a1", "b": "b1", "cs": [{"id": "id_not_main_2", "fk": "id_main_1", "d": "d2", "e": "e3"}]}
OBS: consider that the constraints of and between main and not_main are properly modeled, e.g., that I actually have both id columns as PKs and that fk is references the id column of main.
You want json array aggregation. Basically, you just need to change json_build_array() to json_agg(), and to add a group by clause:
select
json_build_object(
'id', m.id,
'a', m.a,
'b', m.b,
'cs', json_agg(
json_build_object(
'd', nm.d,
'e', nm.e
)
)
)
from main m
left join not_main nm on
nm.requisitionId = m.id
group by m.id, m.a, m.b

Postgres Build Complex JSON Object from Wide Column Like Design to Key Value

I could really use some help here before my mind explodes...
Given the following data structure:
SELECT * FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);
day | apple | banana | orange
-----+-------+--------+--------
1 | 1 | 1 | 1
2 | 2 | 2 | 2
I want to construct a JSON object which looks like the following:
{
"data": [
{
"day": 1,
"fruits": [
{
"key": "apple",
"value": 1
},
{
"key": "banana",
"value": 1
},
{
"key": "orange",
"value": 1
}
]
}
]
}
Maybe I am not so far away from my goal:
SELECT json_build_object(
'data', json_agg(
json_build_object(
'day', t.day,
'fruits', t)
)
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);
Results in:
{
"data": [
{
"day": 1,
"fruits": {
"day": 1,
"apple": 1,
"banana": 1,
"orange": 1
}
}
]
}
I know that there is json_each which may do the trick. But I am struggling to apply it to the query.
Edit:
This is my updated query which, I guess, is pretty close. I have dropped the thought to solve it with json_each. Now I only have to return an array of fruits instead appending to the fruits object:
SELECT json_build_object(
'data', json_agg(
json_build_object(
'day', t.day,
'fruits', json_build_object(
'key', 'apple',
'value', t.apple,
'key', 'banana',
'value', t.banana,
'key', 'orange',
'value', t.orange
)
)
)
) FROM (VALUES (1, 1, 1, 1), (2, 2, 2, 2)) AS t(day, apple, banana, orange);
Would I need to add a subquery to prevent a nested aggregate function?
Use the function jsonb_each() to get pairs (key, value), so you do not have to know the number of columns and their names to get a proper output:
select jsonb_build_object('data', jsonb_agg(to_jsonb(s) order by day))
from (
select day, jsonb_agg(jsonb_build_object('key', key, 'value', value)) as fruits
from (
values (1, 1, 1, 1), (2, 2, 2, 2)
) as t(day, apple, banana, orange),
jsonb_each(to_jsonb(t)- 'day')
group by 1
) s;
The above query gives this object:
{
"data": [
{
"day": 1,
"fruits": [
{
"key": "apple",
"value": 1
},
{
"key": "banana",
"value": 1
},
{
"key": "orange",
"value": 1
}
]
},
{
"day": 2,
"fruits": [
{
"key": "apple",
"value": 2
},
{
"key": "banana",
"value": 2
},
{
"key": "orange",
"value": 2
}
]
}
]
}

Postgres order by price lowest to highest using jsonb array

Say I have the following product schema which has common properties like title etc, as well as variants in an array.
How would I go about ordering the products by price lowest to highest?
drop table if exists product;
create table product (
id int,
data jsonb
);
insert into product values (1, '
{
"product_id": 10000,
"title": "product 10000",
"variants": [
{
"variantId": 100,
"price": 9.95,
"sku": 100,
"weight": 388
},
{
"variantId": 101,
"price": 19.95,
"sku": 101,
"weight": 788
}
]
}');
insert into product values (2, '
{
"product_id": 10001,
"title": "product 10001",
"variants": [
{
"variantId": 200,
"price": 89.95,
"sku": 200,
"weight": 11
},
{
"variantId": 201,
"price": 99.95,
"sku": 201,
"weight": 22
}
]
}');
insert into product values (3, '
{
"product_id": 10002,
"title": "product 10002",
"variants": [
{
"variantId": 300,
"price": 1.00,
"sku": 300,
"weight": 36
}
]
}');
select * from product;
1;"{"title": "product 10000", "variants": [{"sku": 100, "price": 9.95, "weight": 388, "variantId": 100}, {"sku": 101, "price": 19.95, "weight": 788, "variantId": 101}], "product_id": 10000}"
2;"{"title": "product 10001", "variants": [{"sku": 200, "price": 89.95, "weight": 11, "variantId": 200}, {"sku": 201, "price": 99.95, "weight": 22, "variantId": 201}], "product_id": 10001}"
3;"{"title": "product 10002", "variants": [{"sku": 300, "price": 1.00, "weight": 36, "variantId": 300}], "product_id": 10002}"
Use jsonb_array_elements() to unnest variants, e.g.:
select
id, data->'product_id' product_id,
var->'sku' as sku, var->'price' as price
from
product, jsonb_array_elements(data->'variants') var
order by 4;
id | product_id | sku | price
----+------------+-----+-------
3 | 10002 | 300 | 1.00
1 | 10000 | 100 | 9.95
1 | 10000 | 101 | 19.95
2 | 10001 | 200 | 89.95
2 | 10001 | 201 | 99.95
(5 rows)