Объединить все строковые значения объектов JSON

#mysql #mysql-json

Вопрос:

В столбце JSON MySQL 8 у меня есть объект JSON со значениями разных типов (но без вложенных объектов). Подобный этому:

 {
    "abc": "Something123",
    "foo": 63.4,
    "bar": "Hi world!",
    "xyz": false
}
 

Каков самый простой способ выбора объединенных строковых значений? В качестве примера, из приведенного выше JSON мы должны получить "Something123 Hi world!" ?

Ответ №1:

Вот решение для MySQL 8.0:

 select group_concat(json_unquote(json_extract(t.data, concat('$.', j.`key`))) separator '') as joined_string 
from mytable cross join json_table(json_keys(mytable.data), '$[*]' columns (`key` varchar(20) path '

Вывод с учетом ваших примерных данных:

  ----------------------- 
| joined_string         |
 ----------------------- 
| Something123Hi world! |
 ----------------------- 
 

Однако я задаюсь вопросом, является ли это хорошей идеей для хранения данных в JSON, если вам нужно это сделать. Решение является сложным в разработке, и его будет трудно отладить или изменить.

Использование JSON для хранения данных в виде документа, когда вы действительно хотите, чтобы предикаты SQL обрабатывали поля документа как отдельные элементы, сложнее, чем использование обычных строк и столбцов.

Если вы используете MySQL 5.7 или более ранней версии, то функция JSON_TABLE() не поддерживается. В этом случае я бы предложил загрузить весь документ JSON в ваше приложение и превратить его в объект, которым вы можете управлять.

Комментарии:

1. Билл, спасибо за твой ответ. К сожалению, ваше решение очень медленное. На столе с 10 тысячами строк он работал в течение 10 минут, и мне пришлось прервать его. Смотрите мой ответ - он использует аналогичные функции JSON, но занял 0,1 секунды на той же таблице.

2. Что касается "Однако мне интересно, хорошая ли это идея хранить данные в JSON, если вам нужно это сделать": Да, в моем случае JSON отлично работает. Не делайте выводов только из одного странного запроса, который мне иногда нужно было бы выполнить. :)

3. Справедливо. Это правда, что любой вид денормализации является преимуществом для определенных запросов, и если это те запросы, которые вам нужно оптимизировать большую часть времени, то это чистая победа. Но каждый тип оптимизации влечет за собой штраф для других типов запросов.

Ответ №2:

Вот решение:

 SELECT GROUP_CONCAT(va SEPARATOR ' ') str_vals_only
FROM
(
    SELECT id, JSON_UNQUOTE(JSON_EXTRACT(my_json_col, CONCAT('$.', j.obj_key))) va
    FROM my_tbl,
    JSON_TABLE(JSON_KEYS(my_json_col), '$[*]' COLUMNS(obj_key TEXT PATH "$")) j
    WHERE JSON_TYPE(JSON_EXTRACT(my_json_col, CONCAT('$.', j.obj_key))) = 'STRING'
) a
GROUP BY id
 

Не очень просто и лаконично, но я думаю, что это все, что может быть.

Мне нравится поддержка JSON в MySQL. Для некоторых конкретных случаев тип JSON может обеспечить очень хорошее и гибкое решение. Это главная причина, по которой я даже не думаю о переходе на MariaDB (у которого гораздо более ограниченная поддержка JSON). Но я хотел бы, чтобы было больше функций для манипулирования JSON. JSON_TABLE Функция очень мощная, но она может быть немного сложной и многословной.

)) j
join mytable t on json_type(json_extract(t.data, concat('$.', j.`key`)))='STRING';
Вывод с учетом ваших примерных данных:


Однако я задаюсь вопросом, является ли это хорошей идеей для хранения данных в JSON, если вам нужно это сделать. Решение является сложным в разработке, и его будет трудно отладить или изменить.

Использование JSON для хранения данных в виде документа, когда вы действительно хотите, чтобы предикаты SQL обрабатывали поля документа как отдельные элементы, сложнее, чем использование обычных строк и столбцов.

Если вы используете MySQL 5.7 или более ранней версии, то функция JSON_TABLE() не поддерживается. В этом случае я бы предложил загрузить весь документ JSON в ваше приложение и превратить его в объект, которым вы можете управлять.

Комментарии:

1. Билл, спасибо за твой ответ. К сожалению, ваше решение очень медленное. На столе с 10 тысячами строк он работал в течение 10 минут, и мне пришлось прервать его. Смотрите мой ответ — он использует аналогичные функции JSON, но занял 0,1 секунды на той же таблице.

2. Что касается «Однако мне интересно, хорошая ли это идея хранить данные в JSON, если вам нужно это сделать»: Да, в моем случае JSON отлично работает. Не делайте выводов только из одного странного запроса, который мне иногда нужно было бы выполнить. 🙂

3. Справедливо. Это правда, что любой вид денормализации является преимуществом для определенных запросов, и если это те запросы, которые вам нужно оптимизировать большую часть времени, то это чистая победа. Но каждый тип оптимизации влечет за собой штраф для других типов запросов.

Ответ №2:

Вот решение:


Не очень просто и лаконично, но я думаю, что это все, что может быть.

Мне нравится поддержка JSON в MySQL. Для некоторых конкретных случаев тип JSON может обеспечить очень хорошее и гибкое решение. Это главная причина, по которой я даже не думаю о переходе на MariaDB (у которого гораздо более ограниченная поддержка JSON). Но я хотел бы, чтобы было больше функций для манипулирования JSON. JSON_TABLE Функция очень мощная, но она может быть немного сложной и многословной.