Запрос MySql с Json

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

У меня есть таблица в базе данных с именем home_slider.

Внутри у меня есть следующие столбцы:

id_shop, id_lang, id_image and json_groups_id.

Это все поля INT, кроме json_groups_id, куда я вставляю файлы через json_econde.

JSON в поле «json_groups_id» имеет следующую структуру:

{"2": "Guest", "3": "Customer", "4": "Custom"}

Все эти данные сохраняются в простом виде.

В конце концов я нахожу себе разные похожие на это:

+------------+----------------+-----------------+-------------------------------+
|   shop_id  |    id_lang     |   id_image | json_groups_id                     |
+------------+----------------+-----------------+--------------------------------+
|       1    |        1       |      2     | {"2": "Guest", "3": "Customer"}     |
|       1    |        1       |      3     | {"1": "Visit", "4": "Other"}        |
|       1    |        1       |      4     | {"2": "Guest", "5": "Test"}
+-------------+----------------+-----------------+--------------------------------+

Проблема возникает сейчас, учитывая массив, подобный этому [2,5,4]. Я хотел бы получить все строки, которые в поле «json_groups_id» имеют этот ключ. Я пробовал с JSON_EXTRACT, но не смог. Какой выбор я могу использовать? Спасибо Марио

Просто быстрая проверка... Какую версию MySQL вы используете?

RiggsFolly 18.03.2019 15:32

Покажите свой запрос и версию MySql

Justinas 18.03.2019 15:40

TBH Я не очень доволен подходом к фильтрации данных непосредственно по столбцу, который содержит «необработанные данные»/поле объекта, такое как JSON. В качестве наивной идеи, не было бы более разумно изобразить такого рода ассоциации в отдельной таблице, чтобы вы могли запросить их просто по идентификатору?

thex 18.03.2019 15:44

в локальной версии 5.6.35

Mario gasparella 18.03.2019 16:31

Я еще не видел ни одного вопроса на Stack Overflow о хранении JSON в MySQL, где использование JSON было хорошей идеей. Данные лучше хранить в нормализованном виде.

Bill Karwin 18.03.2019 16:35

В MySQL 5.6 вы не можете использовать функции JSON. Взгляните на мой ответ здесь: stackoverflow.com/questions/37816269/… -- эти функции могут оказаться полезными и для вас.

gaborsch 18.03.2019 17:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
6
143
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы должны нормализовать свою базу данных, имея по крайней мере 3-ю нормальную форму. Так атомарные данные лежали бы в отдельном поле. Затем вы можете легко выбрать данные, используя условие WHERE, но в качестве костыля вы можете использовать LIKE для текущей структуры.

SELECT * FROM `table` WHERE `json_groups_id` LIKE '{"YOURNUMBER1"%' OR `json_groups_id` LIKE '{"YOURNUMBER2"%' OR `json_groups_id` LIKE '{"YOURNUMBER3"%'

Также вы можете попробовать JSON_CONTAINS()https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html

Но это не лучшая практика, имхо

Я тоже думаю, что это был бы выход. Разделите данные в другой таблице, чтобы вы могли легко запрашивать их без необходимости применять довольно медленные фильтры к столбцу. Отношение 1:N. Кроме того, это облегчит расширение в будущем.

thex 18.03.2019 15:54
Ответ принят как подходящий

Основываясь на предоставленной вами информации, я предполагаю, что вам нужно отношение M:N, чтобы отобразить вашу связь между данными JSON и исходной таблицей, которую вы описали в своем сообщении.

Ваша исходная таблица (обновлена)

+------------+----------------+------------+
|   shop_id  |    id_lang     |   id_image |
+------------+----------------+------------+
|       1    |        1       |      2     |
|       1    |        1       |      3     |
|       1    |        1       |      4     | 
+------------+----------------+------------+

Новая таблица

+-------------+----------------+
|   group_id  |    desc/name   |
+-------------+----------------+
|       1     |    Visit       |
|       2     |    Guest       |
|       3     |    Customer    |
|       4     |    Other       |
|       5     |    Test        |
+-------------+----------------+

Отношения/присоединение к таблице:

+-------------+-------------------+
| FK group_id | FK Original Table |
+-------------+-------------------+
|       1     |          A        |
|       1     |          B        |
|       2     |          C        |
|       4     |          D        |
|       5     |          E        |
+-------------+-------------------+

Очевидно, что в этом случае вам нужно либо сохранить JSON как дубликат, либо, что было бы еще лучше, и это также то, что я бы рекомендовал => восстановить его из данных, которые вы извлекаете из БД.

Приведенный выше пример таблицы является лишь намеком на то, как это можно реализовать на уровне БД. Если вам не нужна реконструкция данных, я бы вообще не стал беспокоиться об исходном JSON. Я не знаю, каков первичный ключ вашей исходной таблицы, поэтому я добавил общий ключ для таблицы соединений.

Обновлено: удалено 1:N, потому что требуется M:N.

хорошо, я, кажется, понял, что подход неправильный. Я пытаюсь создать две таблицы и связать их друг с другом. По сути, я хочу получить все id_image, принадлежащие одной или нескольким группам id_group, которые у меня есть в массиве. Теперь я пытаюсь связать таблицы, посмотрим, что произойдет

Mario gasparella 18.03.2019 16:35

@Mariogasparella Если один и тот же идентификатор группы относится к разным строкам, вам нужно M: N и второй подход. Однако теперь я обновлю свой ответ, так как вам нужно M: N, насколько я понимаю. Потому что у вас один и тот же идентификатор группы в нескольких строках.

thex 18.03.2019 17:09

@Mariogasparella понять это без JSON в столбце гораздо проще и сложнее. Я знаю, что это может быть больше работы в первую очередь, но это путь. Кроме того, гораздо проще расширить, если вам нужно добавить больше информации в вашу группу.

thex 18.03.2019 17:18

спасибо, ребята, я должен был принять во внимание также директивы и бизнес-решения ... в то время, когда я использовал JSON_EXTRACT, но я переписываю код для создания реляционной таблицы. Большое спасибо за совет

Mario gasparella 20.03.2019 09:42

Вы определенно можете это сделать, используя функцию JSON_EXTRACT() в mysql. Возможно, вы делаете ту или иную ошибку. Позвольте мне объяснить это на примере:

давайте возьмем таблицу, содержащую JSON (таблица client_services здесь):

+-----+-----------+--------------------------------------+
| id  | client_id | service_values                       |
+-----+-----------+------------+-------------------------+
| 100 |      1000 | { "quota": 1,"data_transfer":160000} |
| 101 |      1000 | { "quota": 2,"data_transfer":800000} |
| 102 |      1000 | { "quota": 3,"data_transfer":70000}  |
| 103 |      1001 | { "quota": 1,"data_transfer":97000}  |
| 104 |      1001 | { "quota": 2,"data_transfer":1760}   |
| 105 |      1002 | { "quota": 2,"data_transfer":1060}   |
+-----+-----------+--------------------------------------+

Чтобы выбрать каждое поле JSON, выполните этот запрос:

SELECT 
    id, client_id, 
    json_extract(service_values, '$.quota') AS quota,
    json_extract(service_values, '$.data_transfer') AS data_transfer
FROM client_services;

Таким образом, вывод будет:

+-----+-----------+----------------------+
| id  | client_id | quota | data_transfer|
+-----+-----------+----------------------+
| 100 |      1000 |     1 |       160000 |
| 101 |      1000 |     2 |       800000 |
| 102 |      1000 |     3 |        70000 |
| 103 |      1001 |     1 |        97000 |
| 104 |      1001 |     2 |         1760 |
| 105 |      1002 |     2 |         1060 |
+-----+-----------+----------------------+

Я знаю, что вы пробовали это с помощью json_extract() , но это может быть так, что вы допустили небольшую ошибку. Внимательно изучите этот пример, я уверен, что он сработает.

Другие вопросы по теме