Select rows with specific value in JSON column - mysql

I have a column in MySQL which has an array of JSON with multi objects, this is one of its values:
[
{
"date": "2014-01-17T00:00:00.000Z",
"price": "56.89845204047926330304107978008687496185302734375",
"total": "105774.2223432509504803533673",
"amount": 1859,
"symbol": "fb",
"transaction_code": "buy"
},
{
"date": "2015-04-20T00:00:00.000Z",
"price": "121.497274059658224132363102398812770843505859375",
"total": "962865.8969227914262489775865",
"amount": 7925,
"symbol": "aapl",
"transaction_code": "buy"
},
{
"date": "2013-11-06T00:00:00.000Z",
"price": "49.18047492858931235559794004075229167938232421875",
"total": "330738.6938947631255913961468",
"amount": 6725,
"symbol": "fb",
"transaction_code": "sell"
}
]
I want to extract objects with "transaction_code": "sell" and find the average price of them.

In MySQL 8.0, you can use the JSON_TABLE() function to transform the data so you can apply a WHERE clause to it.
SELECT AVG(j.price)
FROM mytable CROSS JOIN JSON_TABLE(mytable.example_json, '$[*]' COLUMNS(
date DATETIME PATH '$.date',
price DOUBLE PATH '$.price',
total DOUBLE PATH '$.total',
amount INT PATH '$.amount',
symbol VARCHAR(10) PATH '$.symbol',
transaction_code VARCHAR(10) PATH '$.transaction_code'
)
) AS j
WHERE j.transaction_code = 'sell';
This works all right, but it will be bound to have poor performance, and it's more work to write the code every time you want to do this.
In versions of MySQL before 8.0, you're out of luck. Fetch the whole JSON document into a client application, deserialize it into a data structure, and write custom code to loop over it.
It would be better to talk to whomever decided to use JSON to store this data, and convince them to use normal rows and columns. The queries will be easier, and you can create indexes to optimize them.
Also use the DECIMAL type for currency values, not DOUBLE. No one wants to make exact change for 56.89845204047926330304107978008687496185302734375!

Related

Use JSON file in postgresql database

I have a table in a postgresql database with one field with json format.
It's look like this :
[
{
"transition": "transition1",
"from": "step1",
"to": "step2",
"date": {
"date": "2021-01-30 15:34:06.840859"
}
},
{
"transition": "transition2",
"from": "step2",
"to": "step3",
"date": {
"date": "2021-01-30 16:52:00.412208"
}
}
]
I want to have a new column with the date of transition1.
I tried a lot of things but I can't figure out how to extract this date, I can't use the index because the number of transition is not fixed, some user could have 3 and other more than 10.
You need to iterate over all array elements to find the correct one:
select (select (item -> 'date' ->> 'date')::timestamp
from jsonb_array_elements(jsonb_column) as x(item)
where item ->> 'transition' = 'transition1') as transition_date
from the_table
;
If you column is defined as json rather than jsonb (which it should be) you need to use json_array_elements() instead.

How to store different kind of datas in single bucket in couchbase

I want to store the diff kind of data in same bucket in Couchbase, am googled its suggest doc_type and type parameter , but i don't know how i implement that one in my data,I tried below code but i don't know how to do that?
i didn't seen any example,any help will be appreciate,
JsonObject doc = JsonObject.fromJson(consumerRecord.value().toString());
String id=consumerRecord.key().toString();
bucket.upsert(JsonDocument.create(id, doc));
Couchbase buckets store documents of any kind. You don't have to do anything special. As long as it's valid JSON, it can be stored in a Couchbase bucket.
Now, what you might want is some way to differentiate between different types of documents (for querying purposes, for instance). So, you can put a "type" field (or docType or whatever you'd like) as a kind of 'marker' value. You can see examples of this in the built-in travel-sample bucket. For instance, look at the airline_10 and the route_10000 documents:
airline_10
{
"callsign": "MILE-AIR",
"country": "United States",
"iata": "Q5",
"icao": "MLA",
"id": 10,
"name": "40-Mile Air",
"type": "airline"
}
route_10000
{
"airline": "AF",
"airlineid": "airline_137",
"destinationairport": "MRS",
"distance": 2881.617376098415,
"equipment": "320",
"id": 10000,
"schedule": [ ... ],
"sourceairport": "TLV",
"stops": 0,
"type": "route"
}
Notice that one has a type of "airline", the other has a type of "route". An example of a query to find routes:
SELECT t.*
FROM `travel-sample` t
WHERE t.type = 'route'
LIMIT 10
This is one way to differentiate documents. Also notice that the keys are constructed semantically, so they could also be used. Neither of these are a requirement, so it really depends on how you plan to access documents.

Select Objects from Array of Objects that match a property in MYSQL JSON

I have a table with 1 JSON type column city in a MySQL database that stores a JSON array of city objects with following structure:
{
"cities": [
{
"id": 1,
"name": "Mumbai",
"countryID": "9"
},
{
"id": 2,
"name": "New Delhi",
"countryID": "9"
},
{
"id": 3,
"name": "Abu Dhabi",
"countryID": "18"
}
]
}
I want to select objects from the cities array having countryID = 90 but I am stuck as the array of objects is stored in a single column city which is preventing me from doing a (*) with WHERE JSON_CONTAINS(city->'$.cities', JSON_OBEJECT('countryID', '90')).
My query looks like this and I am not getting anywhere,
SELECT JSON_EXTRACT(city, '$.cities') FROM MyTable WHERE JSON_CONTAINS(city->'$.cities', JSON_OBJECT('countryID', '90'))
It'd be a great help if someone can point me in right direction or gimme a solution to this.
Thanks
If you are using MySQL 8.0, there is a feature called JSON table functions. It converts JSON data into tabular form.Then onward you can filter the result.
The query to acheive the same is given below
Select country
FROM json_cal,
JSON_TABLE(
city,
"$.cities[*]" COLUMNS(
country JSON PATH "$",
NESTED PATH '$.countryID' COLUMNS (countryID TEXT PATH '$')
)
) AS jt1
where countryID = 90;
The DB Fiddle can be found here
More information on JSON Table functions can be found here

MySQL join json

To avoid using temporary tables, I hoped to store some data as a json array within a variable and join on it. The data looks something like this:
[
{
"CarID": "9",
"Tank": "11.4",
"Distance": "120",
"From": "Brussels",
"To": "Bruges"
},
{
"CarID": "22",
"Tank": "15.9",
"Distance": "70",
"From": "Eupen",
"To": "Cologne"
}
]
I would like to set a variable in mysql to that value and be able to do something like the following:
SELECT
(
Cars.Consumption
* JSON_UNQUOTE(JSON_something('???','$.Distance'))
) - JSON_UNQUOTE(JSON_something('???','$.Tank')) AS neededRefuel
FROM Cars
WHERE JSON_SEARCH(
#myJson,
'one',
CAST(Cars.CarID AS JSON),
NULL,
'$[*].CarID'
) IS NOT NULL
This is just a simplified example.
Apparently json values as integer are not easy to detect in mysql, so I set quotes.
I wanted to use this kind of filter within a view, so temporary tables are not really an option.
Using MySQL 8.0.11
I just humbled upon JSON_TABLE and it seems to do exactly what I want :)

Access deeper elements of a JSON using postgresql 9.4

I want to be able to access deeper elements stored in a json in the field json, stored in a postgresql database. For example, I would like to be able to access the elements that traverse the path states->events->time from the json provided below. Here is the postgreSQL query I'm using:
SELECT
data#>> '{userId}' as user,
data#>> '{region}' as region,
data#>>'{priorTimeSpentInApp}' as priotTimeSpentInApp,
data#>>'{userAttributes, "Total Friends"}' as totalFriends
from game_json
WHERE game_name LIKE 'myNewGame'
LIMIT 1000
and here is an example record from the json field
{
"region": "oh",
"deviceModel": "inHouseDevice",
"states": [
{
"events": [
{
"time": 1430247045.176,
"name": "Session Start",
"value": 0,
"parameters": {
"Balance": "40"
},
"info": ""
},
{
"time": 1430247293.501,
"name": "Mission1",
"value": 1,
"parameters": {
"Result": "Win ",
"Replay": "no",
"Attempt Number": "1"
},
"info": ""
}
]
}
],
"priorTimeSpentInApp": 28989.41467999999,
"country": "CA",
"city": "vancouver",
"isDeveloper": true,
"time": 1430247044.414,
"duration": 411.53,
"timezone": "America/Cleveland",
"priorSessions": 47,
"experiments": [],
"systemVersion": "3.8.1",
"appVersion": "14312",
"userId": "ef617d7ad4c6982e2cb7f6902801eb8a",
"isSession": true,
"firstRun": 1429572011.15,
"priorEvents": 69,
"userAttributes": {
"Total Friends": "0",
"Device Type": "Tablet",
"Social Connection": "None",
"Item Slots Owned": "12",
"Total Levels Played": "0",
"Retention Cohort": "Day 0",
"Player Progression": "0",
"Characters Owned": "1"
},
"deviceId": "ef617d7ad4c6982e2cb7f6902801eb8a"
}
That SQL query works, except that it doesn't give me any return values for totalFriends (e.g. data#>>'{userAttributes, "Total Friends"}' as totalFriends). I assume that part of the problem is that events falls within a square bracket (I don't know what that indicates in the json format) as opposed to a curly brace, but I'm also unable to extract values from the userAttributes key.
I would appreciate it if anyone could help me.
I'm sorry if this question has been asked elsewhere. I'm so new to postgresql and even json that I'm having trouble coming up with the proper terminology to find the answers to this (and related) questions.
You should definitely familiarize yourself with the basics of json
and json functions and operators in Postgres.
In the second source pay attention to the operators -> and ->>.
General rule: use -> to get a json object, ->> to get a json value as text.
Using these operators you can rewrite your query in the way which returns correct value of 'Total Friends':
select
data->>'userId' as user,
data->>'region' as region,
data->>'priorTimeSpentInApp' as priotTimeSpentInApp,
data->'userAttributes'->>'Total Friends' as totalFriends
from game_json
where game_name like 'myNewGame';
Json objects in square brackets are elements of a json array.
Json arrays may have many elements.
The elements are accessed by an index.
Json arrays are indexed from 0 (the first element of an array has an index 0).
Example:
select
data->'states'->0->'events'->1->>'name'
from game_json
where game_name like 'myNewGame';
-- returns "Mission1"
select
data->'states'->0->'events'->1->>'name'
from game_json
where game_name like 'myNewGame';
This did help me