So you have been lured into storing attribute data as JSON in your MySQL to avoid defining a proper schema from the beginning. Well, now for some report you need a certain attribute as column. Here is how to solve this task.
We have following simplified schema:
CREATE TABLE `store` (
`storeId` int(11) NOT NULL,
`attributes` json DEFAULT NULL
);
With data as in following example:
storeId: 4644
attributes: [
{
"value": "",
"attributeId": "representedBy"
},
{
"value": "abc_de",
"locale": "de_DE",
"attributeId": "terms"
},
{
"value": false,
"attributeId": "hidden"
}
]
We may want to extract the value of attribute representedBy
as column in our report. So to extract we use following trick
select storeId,
cast(
json_unquote(
json_extract(attributes,
json_unquote(
replace(
json_search(attributes, 'one', 'representedBy'),
'attributeId', 'value'
)
)
)
) as char) as representedBy
from store
How does it work:
json_search(attributes, 'one', 'representedBy')
searches the first occurrence of „representedBy“ and returns the path to the key where it is stored- using
replace
we modify the path to point to the value instead of the attributeId - after
json_unquote
we can use that path injson_extract
. The return value is again unquoted and casted to char to have a proper string in the report
Why do we have to use that trick?
We can’t extract the attribute value by using the function json_extract
directly because
- JSON paths which are used in
json_extract
for selection don’t provide selection based on keyValues – you can only select by keyName json_extract
doesn’t separate selection from evaluation – what is selected is evaluated.- Feature request: with both features added we could extract using
json_extract(attributes, '$[*].attributeId="representedBy"', '$.value')