Array (name, value) to map.
[{'name':'email,'value':'email#email.em'},{'name':'phone','value':123123}]
to
{'email':'email#email.em','phone':123123}
I need to organize search and sorting such email and I would like to simplify to make View my Table with map data struct.
with t(id,j) as (
values(1,'[{"name":"email","value":"email#email.em"},{"name":"phone","value":123123}]'::json))
select json_object_agg(a.j->>'name', a.j->>'value')
from t, json_array_elements(j) a(j) group by id;
╔════════════════════════════════════════════════════╗
║ json_object_agg ║
╠════════════════════════════════════════════════════╣
║ { "email" : "email#email.em", "phone" : "123123" } ║
╚════════════════════════════════════════════════════╝
I changed your input data to actually be json (dbl quotes instead on single and added keyname for array. After this transofrmation here is example of how to "build" it:
t=# with j as (
select '{"arr":[{"name":"email","value":"email#email.em"},{"name":"phone","value":123123}]}'::json v
)
select
concat('{',v->'arr'->0->'name',':',v->'arr'->0->'value',',',v->'arr'->1->'name',':',v->'arr'->1->'value','}')::json
from j
;
{"email":"email#email.em","phone":123123}
Related
Given the following:
create table test (
id int,
status text
);
insert into test values
(1,'[]'),
(2,'[{"A":"d","B":"c"}]'),
(3,'[{"A":"g","B":"f"}]');
Is it possible to return?
id A B
1 null null
2 d c
3 g f
I am attempting something like this:
select id,
status::json ->> 0 #> "A" from test
Try this to address your specific example :
SELECT id, (status :: json)#>>'{0,A}' AS A, (status :: json)#>>'{0,B}' AS B
FROM test
see the result
see the manual :
jsonb #>> text[] → text
Extracts JSON sub-object at the specified path as text.
'{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}' → bar
This does it:
SELECT id,
(status::json->0)->"A" as A,
(status::json->0)->"B" as B
FROM test;
I want to fetch the value from JSON object in BigQuery. I have a JSON like below
{"fruit":[{"apples":5,"oranges":10},{"apples":2,"oranges":4}]}
and the condition to fetch json object value is : if apples = 2 then return value of oranges is 4
How do i iterate through ARRAY in BigQuery?
Consider below example
#standardSQL
with `project.dataset.table` as (
select '{"fruit":[{"apples":5,"oranges":10},{"apples":2,"oranges":4}]}' json
)
select
json_extract(x, '$.oranges') oranges
from `project.dataset.table`,
unnest(json_extract_array(json, '$.fruit')) x
where json_extract(x, '$.apples') = '2'
with output
Hi I am trying to translate this logic from T-sql json query to usql. But i am not able to achieve the same results. Any help will be appreciated.
select N'{
"rowid": "1",
"freeresponses": {
"fr1": "1.1",
"fr2": "1.1",
"fr3": "1.3",
"fr4": "1.4",
"fr5": "1.4"
}
}'as jsontext
into dbo.tmp#
SELECT convert (int, JSON_VALUE(jsontext,'$.rowid' )) as rowid,
c.[key], c.[value]
FROM dbo.tmp#
cross apply openjson(json_query(jsontext,'$.freeresponses') )
as c;
the result will be like this in SQL server.
rowid | key | value
1 | fr1| 1.1
1 | fr2| 1.1
1 | fr3| 1.3
1 | fr4 | 1.4
1 | fr5| 1.4
To achive the same result in USQL i have tried the below and errors.
REFERENCE ASSEMBLY Staging.[Newtonsoft.Json];
REFERENCE ASSEMBLY Staging.[Microsoft.Analytics.Samples.Formats];
USING Microsoft.Analytics.Samples.Formats.Json;
DECLARE #inputmasterfileset string = "/sourcedata/samplefreeresponse.txt";
DECLARE #outputfreeresponse string = "/sourcedata/samplefreeresponseoutput.txt";
#freeresponse1 =
EXTRACT rowid string,
freeresponses string
FROM #inputmasterfileset
USING new JsonExtractor("");
#freeresponse2 =
SELECT rowid,
JsonFunctions.JsonTuple(freeresponses).Values AS freeresponses
FROM #freeresponse1;
#freeresponse3 =
SELECT rowid
,JsonFunctions.JsonTuple(free) AS values
FROM #freeresponse2
CROSS APPLY
EXPLODE(freeresponses) AS c(free);
OUTPUT #freeresponse3
TO #outputfreeresponse
USING Outputters.Text('|', outputHeader:true,quoting:false);
The catch is, i dont know how the keys are named the json document so i cannot specify JsonFunctions.JsonTuple(free)["fr1"] in stage 3 of the code and I want the result as same as what i got in T-SQL.
Much appreciated.
I have resolved it myself. It was the confusion with SQL MAP and SQL ARRAY.
I have a list of movies with ratings by user.
{"_id":59607,"title":"King Corn (2007)",
"genres":["Documentary"],
"ratings":[ {"userId":1860,"rating":3},
{"userId":9970,"rating":3.5},
{"userId":16929,"rating":1.5},
{"userId":23473,"rating":4},
{"userId":23733,"rating":4},
{"userId":27584,"rating":3},
{"userId":28232,"rating":4},
{"userId":29482,"rating":3},
{"userId":40976,"rating":5},
{"userId":44631,"rating":4},
{"userId":47613,"rating":3},
{"userId":49763,"rating":3},
{"userId":58160,"rating":4.5},
{"userId":62249,"rating":3},
{"userId":65923,"rating":4},
{"userId":67507,"rating":4},
{"userId":68259,"rating":3.5},
{"userId":70331,"rating":5},
{"userId":71420,"rating":3.5}
]
}
I need to count how many ratings are done by every user. This is my attempt to get in the ratings.
a = load '/movies_1m.json' using JsonLoader('id:int, title : chararray, genres : { ( genre : chararray ) }, ratings: { ( userId : int, rating: float) } ');
then
b = FOREACH a GENERATE FLATTEN(ratings);
describe give me following:
b: {ratings::userId: int,ratings::rating: float}
just to count the users I need to access the inside of ratings. But this is the point where it is not succeeding. I tried this:
c = FOREACH b GENERATE COUNT(ratings);
it gets me an error.
I need to get something like this:
{userId: int, rating: float}
You need to GROUP in order to COUNT since that is an aggregate operation.
b = FOREACH a GENERATE FLATTEN(ratings);
gr = GROUP b by ratings::userId;
c = FOREACH gr GENERATE group,COUNT($1);
\d c
Output
Note, none of the users in your example repeat, so these are all one.
(1860,1)
(9970,1)
(16929,1)
(23473,1)
(23733,1)
(27584,1)
(28232,1)
(29482,1)
(40976,1)
(44631,1)
(47613,1)
(49763,1)
(58160,1)
(62249,1)
(65923,1)
(67507,1)
(68259,1)
(70331,1)
(71420,1)
I have an object that looks like this one:
object =
title : 'an object'
properties :
attribute1 :
random_number: 2
attribute_values:
a: 10
b: 'irrelevant'
attribute2 :
random_number: 4
attribute_values:
a: 15
b: 'irrelevant'
some_random_stuff: 'random stuff'
I want to extract the sum of the 'a' values on attribute1 and attribute2.
What would be the best way to do this in Coffeescript?
(I have already found one way to do it but that just looks like Java-translated-to-coffee and I was hoping for a more elegant solution.)
Here is what I came up with (edited to be more generic based on comment):
sum_attributes = (x) =>
sum = 0
for name, value of object.properties
sum += value.attribute_values[x]
sum
alert sum_attributes('a') # 25
alert sum_attributes('b') # 0irrelevantirrelevant
So, that does what you want... but it probably doesn't do exactly what you want with strings.
You might want to pass in the accumulator seed, like sum_attributes 0, 'a' and sum_attributes '', 'b'
Brian's answer is good. But if you wanted to bring in a functional programming library like Underscore.js, you could write a more succinct version:
sum = (arr) -> _.reduce arr, ((memo, num) -> memo + num), 0
sum _.pluck(object.properties, 'a')
total = (attr.attribute_values.a for key, attr of obj.properties).reduce (a,b) -> a+b
or
sum = (arr) -> arr.reduce((a, b) -> a+b)
total = sum (attr.attribute_values.a for k, attr of obj.properties)