I am using mariadb version 10.2.43-MariaDB-1:10.2.43+maria~bionic
Table schema
The table has a columns id
attribute and details
array with the following two rows of data :
{
"id": 9,
"details": [
{
"amount": 100,
"flag": true,
"fieldA": "abcd"
},
{
"amount": 101,
"flag": false,
"fieldB": "bcde"
},
{
"amount": 103,
"flag": true,
"fieldA": "abcd"
}
]
},
{
"id": 10,
"details": [
{
"amount": 110,
"flag": false,
"fieldA": "abcd"
},
{
"amount": 102,
"flag": true,
"fieldB": "bcde"
}
]
}
I want to calculate the sum of amounts when the flag is true.
- For id = 9 amounts = [100, 103]
- For id = 10 amounts = [102]
- Total = 100 + 103 + 102 = 305
On searching online I found a few answers suggesting json_table
but we are using older version of mariadb which does not support json_table.
I have used this way to extract the amounts and flags and then finally handled the sum in code.
SELECT JSON_EXTRACT(features,'$. details[*].amount') as amounts,
JSON_EXTRACT(features,'$.details[*].flag') as flag
FROM table
WHERE JSON_EXTRACT(features,'$.details[*].flag') != 'NULL';
Output
-------------------------------------------------------------+---------------------------------------------------------------------+
| [500000, 1000000] | [false, false] |
| [1100000] | [false] |
| [1000000] | [false] |
| [500000, 1000000] | [false, false] |
| [100000] | [false] |
| [5000000] | [false] | |
| [50000] | [false] |
| [500000] | [false] |
| [500000] | [false] |
| [10000] | [true] |
| [49998] | [true] |
| [600000, 399980] | [false, true]
Questions:
- I want to know if the order of elements in amounts array and flag array will be the same as that in details. (otherwise the sum I am calculating will be wrong).
- Is there a more efficient way to calculate the sum without using code?
The documentation says:
So yes, both calls to
json_extract
will give you an ordered slice of the json array. But note that, as far as your query goes, you are still left with the task of unesting each slice (the two arrays that you are getting)... which is the core of the task, and brings us to your second question.MariaDB does not support
json_table
, which can expand a json array to rows. But we can emulate it with the help of a table of numbers and of other MariaDB json functions.There are many different ways that you can create a table of numbers, either inline in the query or permanently stored in a table. Here I am just using a fixed list of a few numbers :
The join on
n
generate one row for each item in the JSON array; given the index of the element, we can generate the proper json path to its amount and flag (that's what theconcat()
s do), and access the values withjson_value()
.I don't have a MariaDB 10.2 database at hand to test, but here is a MariaDB 10.3 fiddle. Note the database properly recognizes the boolean value in the
flag
attribute, which simplifies thewhere
clause.