SQL Server query JSONobject to get aggregated values - sql

I have a JSON object stored in SQL Server, in a nvarchar(max) column. The JSON looks like this:
{
"data": [{
"RespID": 3512,
"ObsPriceValue": 2.34
}, {
"RespID": 4904,
"ObsPriceValue": 2.54
}, {
"RespID": 5127,
"ObsPriceValue": 3.44
}]
}
The above example array is made up of three items, but I don't know how many items are present in the record, and they can be 2 as well as up to 30.
Each row in the table has an object like the above.
I'd like to get, in a single query, the average value of the field ObsPriceValue
I've tried with JSON_QUERY, but I have always to specify the index of the element.
Is there a way to get it or the JSON schema the data is stored is wrong?

Next approach may help. You need to use OPENJSON() with explicit schema definition to return a table with ObsPriceValue column:
JSON:
DECLARE #json nvarchar(max) = N'{"data": [{
"RespID": 3512,
"ObsPriceValue": 2.34
}, {
"RespID": 4904,
"ObsPriceValue": 2.54
}, {
"RespID": 5127,
"ObsPriceValue": 3.44
}]
}'
Statement:
SELECT AVG(ObsPriceValue) AS AvgObsPriceValue
FROM OPENJSON(#json, '$.data') WITH (
ObsPriceValue numeric(10, 2) '$.ObsPriceValue'
) j
Output:
----------------
AvgObsPriceValue
----------------
2.773333

Related

Select JSON object that appears more than one time

I am trying to write a query to return all trains that have more than one etapesSupervision.
My table has a column called DETAIL, in this column I can find the JSON of my train.
"nomTrain": "EVOL99",
"compositionCourtLong": "LONG",
"sillons": [{
"numeroTrain": "EVOL99"
}],
"sillonsV4": [{
"refSillon": "sillons/4289505/2"
}],
"branchesStif": [{
"data": "49",
"data": "BP",
"data": "ORIGINE"
} ],
"etapesSupervision": [{
"data": "PR/0087-758896-00",
"data": "PR/0087-758607-BV",
"superviseur": "1287",
"uoSuperviseur": "B"
},
{
"data": "PR/0087-758607-BV",
"data": "PR/0087-001479-BV",
"superviseur": "1287",
"uoSuperviseur": "B"
}],
This is the query I wrote :
select * from course where CODE_LIGNE_COMMERCIALE='B'
--and ref = 'train/2018-11-12'
and instr(count(train.detail,'"etapesSupervision":'))> 1 ;
Using this, I return trains with only one etapesSupervision.
The thing is the column DETAIL is JSON, so I feel like I can't do a lot with it.
I tried also with like, but it doesn't work either.
Thank you for your comments.
This is the query that worked:
select data,data,data
from train
where
length(DETAIL) - length(replace(DETAIL,'uoSuperviseur',null)) > 20 ;
And this way I have only trains that have more than one supervisor.
Thanks again

SQL Server - JSON type enumeration

Given
declare #json varchar(max)='{
"name":"John",
"age":30,
"cars": [
{ "make":"Ford", "models":[ "Fiesta", "Focus", "Mustang","Vintage"] ,"price":[1100,200,300,999]},
{ "make":"BMW", "models":[ "320", "X3", "X5" ] },
{ "make":"Fiat", "models":[ "500", "Panda" ] }
] }';
The query
select * from openjson(#json,'$')
returns 3 columns:
key value type
I haven't found an enumeration of the type column values and their corresponding meaning.
Please point me in the right direction; thanks.
From the MSDN page for OPENJSON:
Value of the Type column JSON data type
0 null
1 string
2 int
3 true/false
4 array
5 object

Filter an object array to modify json with circe

I am evaluating Circe and couldn't find out how to use filter for arrays to transform a JSON. I read the guide on its website and API doc, still no clue. Help much appreciated.
Sample data:
{
"Department" : "HR",
"Employees" :[{ "name": "abc", "age": 25 }, {"name":"def", "age" : 30 }]
}
Task:
How to use a filter for Employees to transform the JSON to another JSON, for example, all employees with age older than 50?
For some reason I can't filter from data source before JSON is generated, in case you ask.
Thanks
One possible way of doing this is by
val data = """{"Department" : "HR","Employees" :[{ "name": "abc", "age": 25 }, {"name":"def", "age":30}]}"""
def ageFilter(j:Json): Json = j.withArray { x =>
Json.fromValues(x.filter(_.hcursor.downField("age").as[Int].map(_ > 26).getOrElse(false)))
}
val y: Either[ParsingFailure, Json] = parse(data).map( _.hcursor.downField("Employees").withFocus(ageFilter).top.get)
println(s"$y")

How to get each JSON child of an array, postgreSQL

I have postgreSQL 9.3 and working with json, my field json in DB looks like:
{
"route_json": [
{
"someKeys": "someValues",
"time": 123
},
{
"someKeys": "someValues",
"time": 123
}, ... N
]
}
In my case I need to catch the 'time' element from each element of route_json array and set them in new array. Is there any way to do this.
It’s not pretty:
SELECT
value->'time'
FROM
json_array_elements('{"route_json": [{"someKeys": "someValues","time": 123},{"someKeys": "someValues","time": 456}]}'::json->'route_json');

Is there a way to get the Type for a Column using package database/sql in golang?

Basically, without knowing before hand what the resulting structure of a query might be, I'd like to query the database, and return a structure like this (json-y)
// Rows
[
// Row 1
[
{ ColumnName: "id", Value: 1, Type: int },
{ ColumnName: "name", Value: "batman", Type: string },
...
],
// Row 2
[
{ ColumnName: "id", Value: 2, Type: int },
{ ColumnName: "name", Value: "superman", Type: string },
...
]
]
Is there a way to get the Type for a Column using package database/sql in golang?
I'm suspecting that what I want to do is
make an array of interface{} the size of Column(),
then for each column determine it's type,
then fill the array with a pointer to that type,
and then pass the array to Scan()
Which is a little like this code example from sqlx, but without first knowing the Struct that the data would be populating.
You should be able to do it this way:
func printRows(rows *sql.Rows){
colTypes, err := rows.ColumnTypes()
for _,s := range colTypes {
log.Println("cols type:", s.DatabaseTypeName());
}
}
Using database/sql? No (as far as I know).
But you can use this code for arbitrary queries. And json.Marshall() from the json package will use reflection to determine the right way to print a value, so you could have a structure like this:
type Column struct {
ColumnName string
ColumnValue interface{}
ColumnType string
}
And then use reflect.TypeOf(someVariable).String() to get the type for ColumnType.