从MySQL中的JSON数组中删除所有JSON对象

时间:2019-12-01 19:24:55

标签: mysql json

到目前为止,我已经有了它,它只删除了一个对象,应该删除四个对象。

SET @JSON = '[{"one": 5},{"two":2},{"one": 5},{"three":3},{"one": 5},{"one": 5}]';
SET @TO_REMOVE = '{"one": 5}';

SET @JSON = REPLACE(@JSON, @TO_REMOVE, '"DELETED"');
SET @JSON = JSON_REMOVE(@JSON, JSON_UNQUOTE(JSON_SEARCH(@JSON, 'one', 'DELETED')));

SELECT @JSON;

#returns the following:
[{"two": 2}, "DELETED", {"three": 3}, "DELETED", "DELETED"]

我真正想要的是类似上面的方法,但是我不想在JSON_SEARCH中放入“ one”,而是要放入“ all”。有谁知道该怎么做?

SELECT JSON_UNQUOTE(JSON_SEARCH(@JSON, 'one', 'DELETED')) AS `Single`; #returns: $[0]
SELECT JSON_UNQUOTE(JSON_SEARCH(@JSON, 'all', 'DELETED')) AS `Multi`;  #returns: ["$[0]", "$[2]", "$[4]", "$[5]"]

是否有一种方法可以将每个值["$[0]", "$[2]", "$[4]", "$[5]"]传递到JSON_REMOVE中,就像您在JavaScript中使用...进行函数论证一样。

谢谢,也请让我知道替代方法。

1 个答案:

答案 0 :(得分:1)

“残酷”的方式:只需更换它们:

SET @JSON = '[{"one": 5},{"two":2},{"one": 5},{"three":3},{"one": 5},{"one": 5}]';
SET @TO_REMOVE = '{"one": 5}';

SET @JSON = REPLACE(@JSON, CONCAT(@TO_REMOVE, ','), '');
SET @JSON = REPLACE(@JSON, CONCAT(',', @TO_REMOVE), '');
SET @JSON = REPLACE(@JSON, @TO_REMOVE, '');

SELECT @JSON;

结果:

| @JSON                   |
| ----------------------- |
| [{"two":2},{"three":3}] |

View on DB Fiddle

请注意,我们必须处理三种情况:

  • 匹配项,后跟另一个项(其后有,
  • 匹配项,它是最后一项(没有任何项,但前面有,
  • 匹配项,它是数组中的唯一项(不被,包围)

在MySQL 8中:用JSON_TABLE解压缩数组,然后用JSON_ARRAYAGG过滤并再次打包元素:

SET @JSON = '[{"one": 5},{"two":2},{"one": 5},{"three":3},{"one": 5},{"one": 5}]';
SET @TO_REMOVE = '{"one": 5}';

SET @JSON = (
  SELECT JSON_ARRAYAGG(item)
  FROM JSON_TABLE(
    @JSON,
    '$[*]' columns (item JSON path '$')
  ) t
  WHERE item <> CAST(@TO_REMOVE AS JSON)
);

SELECT @JSON;

结果:

| @JSON                      |
| -------------------------- |
| [{"two": 2}, {"three": 3}] |

View on DB Fiddle

请注意,元素的顺序可以更改,因为我们无法控制JSON_ARRAYAGG的顺序。