Select on jsonb array on specific key/value - arrays

I have a jsonb field containing this data :
[{"FieldName":"wire1","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]},
{"FieldName":"wire2","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]},
{"FieldName":"wire3","Metadata":[{"Date":"2018-02-06T11:32:57.4022774+01:00","Source":"exampleSource"}]}]
What is the correct way to access the FieldName = FieldValue inside this array, as part of a select ? We tried SELECT meta::json->0 FROM myTable , and that returned null. (meta is the column's name containing the metaData)
What I hope to get is, in a select, to return all lines where FieldName = wire1, or where Source = exampleSource, or where both are true.

what you need is jsonb_array_elements function.
-> returns an object
SELECT jsonb_array_elements(**columnName**)->'FieldName' FROM ....
returns FieldName object
->> returns text
SELECT jsonb_array_elements(**columnName**)->>'FieldName' FROM ....
returns "wire1" text

Related

OBJECT_CONSTRUCT function is not working properly

output--
I have written the query in snowflake to generate Json file, from the query output want to remove fields which has NULL. OBJECT_CONSTRUCT is not working properly for some column its not passing NULL value where else for some column its giving null value as result.
Input-
Json remove any field which has value NULL or blank.
{"DIFID":122,"DIF_FLAG":"NULL","DIF_TYPE":"asian/white","FOCAL_COUNT":2370,"REFERENCE_COUNT":17304},
Required Output-
Json remove any field which has value NULL or blank.
{"DIFID":122,"DIF_TYPE":"asian/white","FOCAL_COUNT":2370,"REFERENCE_COUNT":17304},
query-
select distinct ITEMSTATID,object_construct(
'DIFID',DIFID,
'DIF_TYPE',DIF_TYPE,
'DIF_FLAG',DIF_FLAG,
'FOCAL_COUNT',FOCAL_COUNT::integer,
'REFERENCE_COUNT',REFERENCE_COUNT::integer,
'DIF_METHOD',DIF_METHOD,
'DIF_VALUE',DIF_VALUE)
DIF
from DEV_IPM.STAGEVAULT.DIF_STATISTICS;
For string column and 'NULL' as string literal column's value is not skipped:
CREATE OR REPLACE TABLE DIF_STATISTICS
AS
SELECT 1 AS ITEMSTATID,
122 AS DIFID,
'NULL' AS DIF_FLAG, -- here
'asian/white' AS DIF_TYPE,
2370 AS FOCAL_COUNT,
17304 AS REFERENCE_COUNT;
Output:
The value is definitely stored as TEXT:
SELECT null AS DIF_FLAG, 'NULL' AS DIF_FLAG;
On the left: true NULL on the right: NULL string
If it the case then it should be nullified NULLIF(DIF_FLAG, 'NULL') before passing to OBJECT_CONSTRUCT function:
SELECT ITEMSTATID,
object_construct(
'DIFID',DIFID,
'DIF_TYPE',DIF_TYPE,
'DIF_FLAG',NULLIF(DIF_FLAG, 'NULL'),
'FOCAL_COUNT',FOCAL_COUNT::integer,
'REFERENCE_COUNT',REFERENCE_COUNT::integer) AS DIF
FROM DIF_STATISTICS;
Previous answer before column details were provided (also plausible):
It is working as intended:
NULL Values
Snowflake supports two types of NULL values in semi-structured data:
SQL NULL: SQL NULL means the same thing for semi-structured data types as it means for structured data types: the value is missing or unknown.
JSON null (sometimes called “VARIANT NULL”): In a VARIANT column, JSON null values are stored as a string containing the word “null” to distinguish them from SQL NULL values.
OBJECT_CONSTRUCT
If the key or value is NULL (i.e. SQL NULL), the key-value pair is omitted from the resulting object. A key-value pair consisting of a not-null string as key and a JSON NULL as value (i.e. PARSE_JSON(‘NULL’)) is not omitted.
For true SQL NULL values, that column is ommitted:
CREATE OR REPLACE TABLE DIF_STATISTICS
AS
SELECT 1 AS ITEMSTATID,
122 AS DIFID,
NULL AS DIF_FLAG,
'asian/white' AS DIF_TYPE,
2370 AS FOCAL_COUNT,
17304 AS REFERENCE_COUNT;
SELECT ITEMSTATID,
object_construct(
'DIFID',DIFID,
'DIF_TYPE',DIF_TYPE,
'DIF_FLAG',DIF_FLAG,
'FOCAL_COUNT',FOCAL_COUNT::integer,
'REFERENCE_COUNT',REFERENCE_COUNT::integer) AS DIF
FROM DIF_STATISTICS;
Output:
Probably the data type of the column DIFID is VARIANT/OBJECT:
CREATE OR REPLACE TABLE DIF_STATISTICS
AS
SELECT 1 AS ITEMSTATID,
122 AS DIFID,
PARSE_JSON('NULL') AS DIF_FLAG, -- here
'asian/white' AS DIF_TYPE,
2370 AS FOCAL_COUNT,
17304 AS REFERENCE_COUNT;
Output:

Postgresql: Append object to a list

I have data that has a key as string and value is a list of json, looks like
ID|data
A1|{key1:[{k1:v1,k2:v2},{{k3:v3,k4:v4}]}
I want to append json, say, {k9:v9,k7:v6} to this list for the key1, something like-
ID|data
A1|{key1:[{k1:v1,k2:v2},{{k3:v3,k4:v4},{k9:v9,k7:v6}]}
I have tried jsonb_set and other functions but they were of no use, example-
UPDATE tbl_name
SET data = jsonb_set(data,'{key1,1}','{k9:v9,k7:v6}'::jsonb) where ID = 'A1'
You need to use jsonb_insert() function in order to append that part, after fixing the format of JSONB value ( otherwise you'd get "ERROR: invalid input syntax for type json" ) :
UPDATE tbl_name
SET data = jsonb_insert(data,'{key1,1}','{"k9":"v9","k7":"v6"}'::jsonb)
WHERE ID = 'A1'
Demo

SQL Server: How to remove a key from a Json object

I have a query like (simplified):
SELECT
JSON_QUERY(r.SerializedData, '$.Values') AS [Values]
FROM
<TABLE> r
WHERE ...
The result is like this:
{ "2019":120, "20191":120, "201902":121, "201903":134, "201904":513 }
How can I remove the entries with a key length less then 6.
Result:
{ "201902":121, "201903":134, "201904":513 }
One possible solution is to parse the JSON and generate it again using string manipulations for keys with desired length:
Table:
CREATE TABLE Data (SerializedData nvarchar(max))
INSERT INTO Data (SerializedData)
VALUES (N'{"Values": { "2019":120, "20191":120, "201902":121, "201903":134, "201904":513 }}')
Statement (for SQL Server 2017+):
UPDATE Data
SET SerializedData = JSON_MODIFY(
SerializedData,
'$.Values',
JSON_QUERY(
(
SELECT CONCAT('{', STRING_AGG(CONCAT('"', [key] ,'":', [value]), ','), '}')
FROM OPENJSON(SerializedData, '$.Values') j
WHERE LEN([key]) >= 6
)
)
)
SELECT JSON_QUERY(d.SerializedData, '$.Values') AS [Values]
FROM Data d
Result:
Values
{"201902":121,"201903":134,"201904":513}
Notes:
It's important to note, that JSON_MODIFY() in lax mode deletes the specified key if the new value is NULL and the path points to a JSON object. But, in this specific case (JSON object with variable key names), I prefer the above solution.

MSSQL JSON_VALUE to match ANY Object in Array

I have a table with a JSON text field:
create table breaches(breach_id int, detail text);
insert into breaches values
( 1,'[{"breachedState": null},
{"breachedState": "PROCESS_APPLICATION",}]')
I'm trying to use MSSQL's in build JSON parsing functions to test whether ANY object in a JSON array has a matching member value.
If the detail field was a single JSON object, I could use:
select * from breaches
where JSON_VALUE(detail,'$.breachedState') = 'PROCESS_APPLICATION'
but it's an Array, and I want to know if ANY Object has breachedState = 'PROCESS_APPLICATION'
Is this possible using MSSQL's JSON functions?
You can use function OPENJSON to check each object, try this query:
select * from breaches
where exists
(
select *
from
OPENJSON (detail) d
where JSON_VALUE(value,'$.breachedState') = 'PROCESS_APPLICATION'
)
Btw, there is an extra "," in your insert query, it should be:
insert into breaches values
( 1,'[{"breachedState": null},
{"breachedState": "PROCESS_APPLICATION"}]')

how to modify an array jsonb in postgresql?

In postgresql,I have a table which defined like this:
create table carts(
id serial,
cart json
)
has data like this:
id cart
3 [{"productid":5,"cnt":6},{"productid":8,"cnt":1}]
5 [{"productid":2},{"productid":7,"cnt":1},{"productid":34,"cnt":3}]
if i want to modify the data "cnt", with id=n and productid=m,
how can I do this?
for example, when id=3,and productid=8, i want to change the cnt to cnt+3,
how to realize it?
Try This, here we will use jsonb_set method
jsonb_set(target jsonb, path text[], new_value jsonb) which will return jsonb object
update carts
set cart = (
(select json_agg(val)from
(SELECT
CASE
WHEN value->>'productid'='8' THEN jsonb_set(value::jsonb, '{cnt}', (((value->>'cnt')::int)+3)::text::jsonb)::json --again convert to json object
ELSE value END val
FROM carts,json_array_elements(cart) where id=3))
where id=3;
Hope it works for you
EDIT: you can generalized this by creating a function with id and
productid as input parameter.

Resources