I have the following table and json values:
database is 'myusers'
column username column jsonstuff
database is 'myusers'
column username column jsonstuff
user1 {'id' : 'user1', 'phones' : [{'id': 'x678', 'brand' : 'apple'},{'id': 'y123', 'brand' : 'samsung'},{'id': 'c458', 'brand' : 'sony'}]}
user2 {'id' : 'user2', 'phones' : [{'id': 'x356', 'brand' : 'apple'},{'id': 'y732', 'brand' : 'samsung'}]}
I want to query all users in the database that have an 'apple' phone, then delete that 'apple' phone from the json array. So the resulting table would look like:
user1 {'id' : 'user1', 'phones' : [{'id': 'y123', 'brand' : 'samsung'},{'id': 'c458', 'brand' : 'sony'}]}
user2 {'id' : 'user2', 'phones' : [{'id': 'y732', 'brand' : 'samsung'}]}
Can this be done in a single query, or do i need a looping function?
For just getting the selection, i have tried:
select json_query(jsonstuff, '$.phones[*]' with wrapper) from myusers where 'brand' = 'apple';
With with no results. It looks like i would need a nested loop or nested query, but not sure how to even start.
Related
I have the following data in one column in BigQuery:
{"id": "81", "type": ["{'id2': '12', 'type2': 'main'}", "{'id2': '15', 'type2': 'sub'}"]}
I would like to parse this and have 'id2' and 'type2' as nested fields. I tried using JSON_VALUE_ARRAY(data, "$.type") that correctly creates the nested rows but couldn't process extracting 'id2' and 'type2'. I believe maybe the "s are the issue inside the list, how could I get past those?
UPDATE:
This is the format I would like to achieve.
Consider below approach
select
json_value(json, '$.id') id, array(
select as struct json_value(trim(type, '"'), '$.id2') as id2, json_value(trim(type, '"'), '$.type2') as type2
from unnest(json_extract_array(json, '$.type')) type
) type
from your_table
I would like to know if there is a way i could get the size of the array of a specific node in a JSON data.
As an example, below is the JSON.
For the node 'Phone' there are two items. I would like to know the size of this node.
My objective is to parse the Java Array to a Java Array.
If i am not aware of the size of the array i would not be able to parse.
Essentially i would like to get the value "2".
{"PONumber" : 1600,
"Reference" : "ABULL-20140421",
"Requestor" : "Alexis Bull",
"User" : "ABULL",
"CostCenter" : "A50",
"ShippingInstructions" : {"name" : "Alexis Bull",
"Address": {"street" : "200 Sporting Green",
"city" : "South San Francisco",
"state" : "CA",
"zipCode" : 99236,
"country" : "United States of America"},
"Phone" : [{"type" : "Office", "number" : "909-555-7307"},
{"type" : "Mobile", "number" : "415-555-1234"}]},
"Special Instructions" : null,
"AllowPartialShipment" : true,
"LineItems" : [{"ItemNumber" : 1,
"Part" : {"Description" : "One Magic Christmas",
"UnitPrice" : 19.95,
"UPCCode" : 13131092899},
"Quantity" : 9.0},
{"ItemNumber" : 2,
"Part" : {"Description" : "Lethal Weapon",
"UnitPrice" : 19.95,
"UPCCode" : 85391628927},
"Quantity" : 5.0}]}
As an alternative, Using the below code i would get that data :
SELECT jt.phones
FROM j_purchaseorder,
JSON_TABLE(po_document, '$.ShippingInstructions'
COLUMNS
(phones VARCHAR2(100) FORMAT JSON PATH '$.Phone')) AS jt;
however if i use
SELECT jt.phones
FROM j_purchaseorder,
JSON_TABLE(po_document, '$'
COLUMNS
(ShippingInstructions VARCHAR2(100) FORMAT JSON PATH '$.ShippingInstructions')) AS jt;
i am getting the value as null.
So how can i get the entire ShippingInstructions in a single value.
For the node 'Phone' there are two items. I would like to know the size of this node.
Essentially i would like to get the value "2".
From this question and this question, you can use:
SELECT jt.phones
FROM j_purchaseorder,
JSON_TABLE(
po_document,
'$.ShippingInstructions'
COLUMNS (
phones VARCHAR2(100) FORMAT JSON WITH WRAPPER PATH '$.Phone.size()'
)
) AS jt;
Which outputs:
PHONES
[2]
If you do not want the array wrapper then you can pass the return value through JSON_VALUE:
SELECT JSON_VALUE(jt.phones, '$[0]') AS phones
FROM j_purchaseorder,
JSON_TABLE(
po_document,
'$.ShippingInstructions'
COLUMNS (
phones VARCHAR2(100) FORMAT JSON WITH WRAPPER PATH '$.Phone.size()'
)
) AS jt;
Which outputs:
PHONES
2
If you are Oracle 19c and your column is defined with an IS JSON check constraint then you can simplify the query to:
SELECT j.po_document."ShippingInstructions"."Phone".size() phones
FROM j_purchaseorder j;
Which outputs:
PHONES
2
If you are using an early Oracle version that does not support the size() function then you can get all rows and use COUNT:
SELECT COUNT(*) AS phones
FROM j_purchaseorder,
JSON_TABLE(
po_document,
'$.ShippingInstructions.Phone[*]'
COLUMNS (
phones VARCHAR2(100) FORMAT JSON PATH '$'
)
) AS jt;
Which outputs:
PHONES
2
db<>fiddle here
I have the following table myTable :
id info
1 {'email': 'bob#bob.com', 'country': 'USA'}
2 {'email': 'test#test.com', 'country': 'DE'}
I would like to update the field country like this :
id info
1 {'email': 'bob#bob.com', 'country': 'country1'}
2 {'email': 'test#test.com', 'country': 'country2'}
I tried this :
UPDATE myTable set info->country : format('country%s', id);
but it does not work
Could you help me please ?
Thank you very much !
There's a whole chapter about that in the official documentation. You'll probably be interested in the json_set or jsonb_set functions.
You can use ||:
update mytable set info = info || jsonb_build_object('country', info ->> 'country' || id::text)
Or using jsonb_set():
update mytable set info = jsonb_set(info, '{country}', to_jsonb(info ->> 'country' || id::text))
I have a column with string entries with the following format (for example)
"[ { 'state' : 'CA', 'tax_amount' : 3},{ 'state' : 'AZ', 'tax_amount' : 4}]"
I want to sum through the tax_amounts in each entry to get a total tax amount for each row. How can I do this in PostgreSQL?
I would use a scalar sub-query:
select t.*,
(select sum((item ->> 'tax_amount')::int)
from jsonb_array_elements(t.the_column) as x(item)) as total_tax
from the_table t
Online example
You can use JSONB_POPULATE_RECORDSET() function such as
WITH t(js) AS
(
SELECT '[ { "state" : "CA", "tax_amount" : 3},
{ "state" : "AZ", "tax_amount" : 4}]'::JSONB
)
SELECT SUM(tax_amount) AS total_tax_amount
FROM t
CROSS JOIN JSONB_POPULATE_RECORDSET(NULL::record,js )
AS tab(state VARCHAR(10), tax_amount INT)
total_tax_amount
----------------
7
after fixing the syntax of the JSON object by replacing single-quotes with double-quotes, and double-quotes wrapping up whole object with single-quotes.
Demo
I am using spark-sql-2.4.1v with java8. I have a scenario where I need to perform certain operation if columns presents in the given dataframe column list
I have Sample data frame as below, the columns of dataframe would differ based on external query executed on the database table.
val data = List(
("20", "score", "school", "2018-03-31", 14 , 12 , 20),
("21", "score", "school", "2018-03-31", 13 , 13 , 21),
("22", "rate", "school", "2018-03-31", 11 , 14, 22),
("21", "rate", "school", "2018-03-31", 13 , 12, 23)
)
val df = data.toDF("id", "code", "entity", "date", "column1", "column2" ,"column3"..."columnN")
as show above dataframe "data" columns are not fixed and would vary and would have "column1", "column2" ,"column3"..."columnN" ...
So depend on the column availability i need to perform some operations
for the same i am trying to use "when-clause" , when a column present then i have to perform certain operation on the specified column else move on to the next operation..
I am trying below two ways using "when-cluase"
First-way :
Dataset<Row> resultDs = df.withColumn("column1_avg",
when( df.schema().fieldNames().contains(col("column1")) , avg(col("column1"))))
)
Second-way :
Dataset<Row> resultDs = df.withColumn("column2_sum",
when( df.columns().contains(col("column2")) , sum(col("column1"))))
)
Error:
Cannot invoke contains(Column) on the array type String[]
so how to handle this scenario using java8 code ?
You can create a column having all the column names. then you can check if the column is present or not and process if it is available-
df.withColumn("columns_available", array(df.columns.map(lit): _*))
.withColumn("column1_org",
when( array_contains(col("columns_available"),"column1") , col("column1")))
.withColumn("x",
when( array_contains(col("columns_available"),"column4") , col("column1")))
.withColumn("column2_new",
when( array_contains(col("columns_available"),"column2") , sqrt("column2")))
.show(false)