JSON query with Snowflake - sql

Hello I have the below json field (addressbooklist) in which im trying to extract addr1 however my code results are NULL
Can someone help?
Query-
select
addressbooklist:addressbook.addressbookAddress.addr1 as test,
from customer;
JSON Field
{
"addressbook": [
{
"addressbookAddress": {
"addr1": "701 N. Brand Boulevard",
"addr2": null,
"addr3": null,
"addrPhone": null,
"addrText": "Executive Software International<br>701 N. Brand Boulevard<br>Glendale CA 912031242<br>United States",
"addressee": "Executive Software International",
"attention": null,
"city": "Glendale",
"country": {
"value": "_unitedStates"
},
"customFieldList": null,
"internalId": null,
"nullFieldList": null,
"override": false,
"state": "CA",
"zip": "912031242"
},
"defaultBilling": false,
"defaultShipping": true,
"internalId": "1587207",
"isResidential": false,
"label": "701 N. Brand Boulevard"
},
{
"addressbookAddress": {
"addr1": "701 N. Brand Boulevard",
"addr2": null,
"addr3": null,
"addrPhone": null,
"addrText": "Executive Software International<br>701 N. Brand Boulevard<br>Glendale CA 912031242<br>United States",
"addressee": "Executive Software International",
"attention": null,
"city": "Glendale",
"country": {
"value": "_unitedStates"
},
"customFieldList": null,
"internalId": null,
"nullFieldList": null,
"override": false,
"state": "CA",
"zip": "912031242"
},
"defaultBilling": true,
"defaultShipping": false,
"internalId": "1587208",
"isResidential": false,
"label": "701 N. Brand Boulevard"
}
],
"replaceAll": false
}

Your json document addressbook element is an array, not a plain property. You can reference a specific element in an array with [0] notation (0=first element, 1=second,...). Your query would look like this:
select addressbooklist:addressbook[0].addressbookAddress.addr1 as test from customer;
If you want to have all of the addressbook items in the result, you can flatten the json structure with this kind of query:
select ab.value:addressbookAddress.addr1 as test
from customer
, lateral flatten(input => addressbooklist:addressbook) ab;
Result:
TEST
"701 N. Brand Boulevard"
"701 N. Brand Boulevard"
More info on Snowflake json syntax for arrays can be found here:
Get single array items: https://docs.snowflake.com/en/user-guide/querying-semistructured.html#retrieving-a-single-instance-of-a-repeating-element
Flatten function to get table from array:
https://docs.snowflake.com/en/user-guide/querying-semistructured.html#using-the-flatten-function-to-parse-arrays

The JSON object you refered to has the following structure:
Array[Object1{key1: value, key2: value}, Object2{key1: value, key2: value}]
Object1 is the first item of your array with the index 0, Object2 has index 1 and so on.
You access an item of an array like Array[0] and you can reach a value inside an object like Object1.key1. In this example you would reach out to key1 like Array[0]Object1.key1.
In your case you can access addr1 in you first object like this:
addressbook[0].addressbookAddress.addr1

It would help to know which language you want to use. I just have to do this with mySQL. Something like this may help:
select
yourField->>'$."addressbookAddress"[0].addr1' as address
from yourTable
where 1

Related

How can I parse through an array of JSON objects with a SQL query?

I am trying to create a SQL query to gather information from a column in a database called "CarOptions". This column is an array that contains 1 or more JSON objects. Below is an example of the array.
I want to only grab the values of the name and the price. Could any provide me a query that can formulate a column with the name and price so that it would look like the example below or any readable format?
"Clear Guard 89500, Tint 0"
[
{
"id": 5,
"name": "Clear Guard",
"type": "ANY",
"grouping": "PREFER",
"price": 89500,
"oemOffering": false,
"learnMoreUrl": null,
"pricePercent": null,
"optionGroupId": 2,
"percentSource": null
},
{
"id": 119600,
"name": "Tint (Lifetime Warranty)",
"type": "NEW",
"grouping": "PREFER",
"price": 0,
"oemOffering": false,
"learnMoreUrl": null,
"pricePercent": null,
"optionGroupId": 18,
"percentSource": null
}
]
you can use openJson to pull the data out. Note you don't state your database, this is for SqlServer.
A very quick hacky example:
declare #json varchar(max)='[ { "id": 5, "name": "Clear Guard", "type": "ANY", "grouping": "PREFER", "price": 89500, "oemOffering": false, "learnMoreUrl": null, "pricePercent": null, "optionGroupId": 2, "percentSource": null }, { "id": 119600, "name": "Tint (Lifetime Warranty)", "type": "NEW", "grouping": "PREFER", "price": 0, "oemOffering": false, "learnMoreUrl": null, "pricePercent": null, "optionGroupId": 18, "percentSource": null } ]'
select j.[key] Id, x.[key], x.[value]
from OpenJson(#json)j
outer apply (
select [key],[value]
from OpenJson(value)
where [key] in ('name','price')
)x
Id key value
---- ---------- -------------------------
0 name Clear Guard
0 price 89500
1 name Tint (Lifetime Warranty)
1 price 0
(4 rows affected)

JSON database table query

I have JSON table with some objects and I am trying to query the amount value in the object
{
"authorizations": [
{
"id": "d50",
"type": "passed",
"amount": 100,
"fortId": 5050,
"status": "GENERATED",
"voided": false,
"cardNumber": 3973,
"expireDate": null,
"description": "Success",
"customerCode": "858585",
"paymentMethod": "cash",
"changeDatetime": null,
"createDatetime": 000000000,
"reservationCode": "202020DD",
"authorizationCode": "D8787"
},
{
"id": "d50",
"type": "passed",
"amount": 100,
"fortId": 5050,
"status": "GENERATED",
"voided": false,
"cardNumber": 3973,
"expireDate": null,
"description": "Success",
"customerCode": "858585",
"paymentMethod": "cash",
"changeDatetime": null,
"createDatetime": 000000000,
"reservationCode": "202020DD",
"authorizationCode": "D8787"
}
],
}
I have tried the following four options, but none of these give me the value of the object:
SELECT info #> 'authorizations:[{amount}]'
FROM idv.reservations;
SELECT info -> 'authorizations:[{amount}]'
FROM idv.reservations;
info -> ''authorizations' ->> 'amount'
FROM idv.reservations
select (json_array_elements(info->'authorizations')->'amount')::int from idv.reservations
note I am using DBeaver
If you want one row per object contained in the "authorizations" JSON array, with the corresponding amount, you can use a lateral join and jsonb_array_elements():
select r.*, (x.obj ->> 'amount')::int as amount
from reservations r
cross join lateral jsonb_array_elements(r.info -> 'authorizations') x(obj)
We can also extract all amounts at once and put them in an array, like so:
select r.*,
jsonb_path_query_array(r.info, '$.authorizations[*].amount') as amounts
from reservations r
Demo on DB Fiddlde

JSON Parsing in Snowflake - Square Brackets At Start

I'm trying to parse out some JSON files in snowflake. In this case, I'd like to extract the "gift card" from the line that has "fulfillment_service": "gift_card". I've had success querying one dimensional JSON data, but this - with the square brackets - is confounding me.
Here's my simple query - I've created a small table called "TEST_WEEK"
select line_items:fulfillment_service
from TEST_WEEK
, lateral flatten(FULFILLMENTS:line_items) line_items;
Hopefully this isn't too basic a question. I'm very new with parsing JSON.
Thanks in advance!
Here's the start of the FULLFILLMENTS field with the info I want to get at.
[
{
"admin_graphql_api_id": "gid://shopify/Fulfillment/2191015870515",
"created_at": "2020-08-10T14:54:38Z",
"id": 2191015870515,
"line_items": [
{
"admin_graphql_api_id": "gid://shopify/LineItem/5050604355635",
"discount_allocations": [],
"fulfillable_quantity": 0,
"fulfillment_service": "gift_card",
"fulfillment_status": "fulfilled",
"gift_card": true,
"grams": 0,
"id": 5050604355635,
"name": "Gift Card - $100.00",
"origin_location": {
"address1": "100 Indian Road",
"address2": "",
"city": "Toronto",
"country_code": "CA",
Maybe you can use two lateral flatten to process values in line_items array:
Sample table:
create table TEST_WEEK( FULFILLMENTS variant ) as
select parse_json(
'[
{
"admin_graphql_api_id": "gid://shopify/Fulfillment/2191015870515",
"created_at": "2020-08-10T14:54:38Z",
"id": 2191015870515,
"line_items": [
{
"admin_graphql_api_id": "gid://shopify/LineItem/5050604355635",
"discount_allocations": [],
"fulfillable_quantity": 0,
"fulfillment_service": "gift_card",
"fulfillment_status": "fulfilled",
"gift_card": true,
"grams": 0,
"id": 5050604355635,
"name": "Gift Card - $100.00",
"origin_location": {
"address1": "100 Indian Road",
"address2": "",
"city": "Toronto",
"country_code": "CA"
}
}
]
}
]');
Sample query:
select s.VALUE:fulfillment_service
from TEST_WEEK,
lateral flatten( FULFILLMENTS ) f,
lateral flatten( f.VALUE:line_items ) s;
The output:
+-----------------------------+
| S.VALUE:FULFILLMENT_SERVICE |
+-----------------------------+
| "gift_card" |
+-----------------------------+
Those square brackets indicate that you have an array of JSON objects in your FULLFILLMENTS field. Unless there is a real need to have an array of objects in one field you should have a look at the STRIP_OUTER_ARRAY property of the COPY command. An example can be found here in the Snowflake documentation:
copy into <table>
from #~/<file>.json
file_format = (type = 'JSON' strip_outer_array = true);
In case others are stuck with same data issue (all json data in one array), I have this solution:
select f.VALUE:fulfillment_service::string
from TEST_WEEK,
lateral flatten( FULFILLMENTS[0].line_items ) f;
With this, you just grab the first element of the array (which is the only element).
If you have nested array elements, just add this to the lateral flatten:
, RECURSIVE => TRUE, mode => 'array'

Yodlee searchSite returning component with multiple values

The Yodlee docs for siteSearch shows a componentList array with each entry looking like this:
{
"valueIdentifier": "LOGIN",
"valueMask": "LOGIN_FIELD",
"fieldType": {
"typeName": "TEXT"
},
"size": 20,
"maxlength": 22,
"name": "LOGIN",
"displayName": "User ID",
"isEditable": true,
"isOptional": false,
"isEscaped": false,
"helpText": "101920",
"isOptionalMFA": false,
"isMFA": false
},
however, when the siteSearch is matches "baa", we get a response with a componentList array entry that seems to have multiple possible values, like this:
{
\"defaultValues\": [
\"6331\",
\"5700\",
null,
null
],
\"values\": [
null,
null,
null,
null
],
\"validValues\": [
null,
null,
null,
null
], ...
I can't find any documentation on this "multiple-value field", and it seems to be a rare case. Can anyone point me to any information on this type?
Thanks.
I would suggest you to check this.
Here look for Social Security Number example. It is a single field which has been divided into 3 section(i.e. input text box). Similarly you need to consume the Login form you are receiving and show it to the consumer of your application.
Whenever you'll find valueIdentifier is having an array i.e. more than 1 value then it is multiple fixed field type else it's a single field.
Here is the image how does it look like once you render the same.

Freebase query with inner joins on the statment

Can I create an inner join on free base that uses another query?
I tried to create a join between 2 querys:
The first, select all the artist that the genre is the same as nirvana without nirvana:
[{
"id": null,
"name": null,
"name!=": "nirvana",
"type": "/music/artist",
"genre": [{
"name|=": [
"Punk rock",
"Grunge",
"Alternative rock",
"Rock music",
"Hardcore punk"
]
}]
}]
the second, select all the genre of nirvana:
[{
"name": "nirvana",
"type": "/music/musical_group",
"/music/artist/genre": []
}]
I want to create a query like this but it does not work.
[{
"id": null,
"name": null,
"name!=": "nirvana",
"type": "/music/artist",
"genre": [{
"name|=":
[{
"name": "nirvana",
"type": "/music/musical_group",
"/music/artist/genre": []
}]
}]
}]
I'm not sure why you need to do this all as one query. Since Nirvana's music spans a number of very popular genres your query will probably return thousands of results which will mean that you'll have to make multiple API requests to get all the results either way.
In any case, here's a MQL query that finds all the bands which have at least one music genre in common with Nirvana:
[{
"id": null,
"name": null,
"/music/artist/genre": [{
"id": null,
"name": null,
"!/music/artist/genre": {
"id": "/m/0b1zz",
"name": null
}
}]
}]
The exclamation mark in front of the 2nd genre property means that we want the inverse relationship ie. "music artists with this genre" instead of "music genres for this artist".
Note that I've used the MID (/m/0b1zz) to represent Nirvana. You shouldn't be using names to identify topics in a query since they're not unique. You want results for the Nirvana started by Kurt Cobain in 1987, not just any band named Nirvana.