Как удалить несколько значений ИЗ MySQL JSON

#mysql #json

#mysql #json

Вопрос:

Мне нужно удалить несколько значений из массива JSON в MySQL

Я пробовал JSON_REMOVE с помощью JSON_SEARCH для каждого значения, но после удаления элемента ИНДЕКС изменяется

Массив JSON:

 ["1", "5", "18", "68"]
 

например: удалите «5» и «68».

ожидаемый результат :

 ["1", "18"]
 

ОТРЕДАКТИРОВАННЫЙ:

код, который я пробовал:

 JSON_REMOVE(`can_see`, JSON_UNQUOTE(JSON_SEARCH(`can_see`, 'one', '5')), JSON_UNQUOTE(JSON_SEARCH(`can_see`, 'one', '68')))
 

результат запроса:

 ["1", "18", "68"]
 

после удаления «5» в индексе $ [0] индекс «68» изменился на $ [2], но JSON_SEARCH возвращает $ [3] из исходного json

Я тоже попробовал вложенный :

 JSON_REMOVE(JSON_REMOVE(`can_see`, JSON_UNQUOTE(JSON_SEARCH(`can_see`, 'one', '5'))), JSON_UNQUOTE(JSON_SEARCH(JSON_REMOVE(`can_see`, JSON_UNQUOTE(JSON_SEARCH(`can_see`, 'one', '5'))), 'one', '68')))
 

это работает, но это становится беспорядочным, если я хочу удалить более 2 значений

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

1. Можете ли вы показать нам, что вы пробовали. Это поможет предоставить контекст вашему вопросу. И какие изменения ИНДЕКСА?

2. Глупый ответ, конечно, состоит в том, чтобы сначала сделать 68 и 5 секунд, тогда индекс не будет проблемой

3. @RiggsFolly мне нужно быть уверенным, что массив отсортирован

4. «мне нужно быть уверенным, что массив отсортирован» я опубликовал ответ, помогает ли это?

Ответ №1:

мне нужно быть уверенным, что массив отсортирован

Не самый простой и понятный способ, но я думаю, вам придется использовать генератор чисел SQL для разбора массива json в виде токенов (записей), которые вы можете фильтровать и упорядочивать более простым способом.

Запрос

 SELECT 
  JSON_ARRAYAGG(
     JSON_EXTRACT(records.json, CONCAT('$[', number_generator.number , ']'))
  ) AS json                                    
FROM (

  SELECT 
   @row := @row   1 AS number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION   SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION  SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row2
  CROSS JOIN (
    SELECT @row := -1 
  ) init_user_params 
) AS number_generator
CROSS JOIN (


SELECT 
    json
  , JSON_LENGTH(records.json) AS json_array_length    
FROM (

  SELECT 
   '["1", "5", "18", "68"]' AS json
  FROM 
   DUAL  
) AS records

) AS records 
WHERE
    number BETWEEN 0 AND  json_array_length - 1   
  AND
    JSON_EXTRACT(records.json, CONCAT('$[', number_generator.number , ']')) NOT IN(5, 68)                   
ORDER BY 
 REPLACE(JSON_EXTRACT(records.json, CONCAT('$[', number_generator.number , ']')), '"', '')                       
 

Результат

 | json        |
| ----------- |
| ["1", "18"] |
 

смотрите демонстрацию

MySQL 8 , с другой стороны, делает это намного проще

Запрос

 SELECT 
 JSON_ARRAYAGG (
    result_table.item
 ) AS json
FROM JSON_TABLE(
     '["1", "5", "18", "68"]'
   , "$[*]"

   COLUMNS (
       rowid FOR ORDINALITY
     , item VARCHAR(100) PATH "$"   
   )
) AS result_table
WHERE
 CAST(result_table.item AS UNSIGNED) NOT IN(5, 68) 
ORDER BY 
 CAST(result_table.item AS UNSIGNED) ASC
 

Результат

 | json        |
| ----------- |
| ["1", "18"] |
 

смотрите демонстрацию

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

1. Большое вам спасибо за ответ, я буду честен, для меня это слишком сложно понять и использовать для моих целей. это часть более крупного запроса на ОБНОВЛЕНИЕ, который УСТАНАВЛИВАЕТ несколько столбцов, версия MySQL — 5.6

2. Да, проблема в том, что создание синтаксического анализатора JSON в MySQL 5.6 намного сложнее, я советую вам обновить свою версию MySQL. Потому что MySQL 5.6 не имел такой большой поддержки JSON. @Double_O_Seven