【问题标题】:How to select JSON object from JSON array field of mysql by some condition如何通过某些条件从 mysql 的 JSON 数组字段中选择 JSON 对象
【发布时间】:2020-06-04 07:34:24
【问题描述】:

我有一个包含 JSON 对象数组的 JSON 字段表。我需要根据某些条件选择对象。

创建并填写表格:

CREATE TABLE test (
    id INT AUTO_INCREMENT PRIMARY KEY,
    json_list JSON
);

INSERT INTO test(json_list) VALUES
("{""list"": [{""type"": ""color"", ""value"": ""red""}, {""type"": ""shape"", ""value"": ""oval""}, {""type"": ""color"", ""value"": ""green""}]}"),
("{""list"": [{""type"": ""shape"", ""value"": ""rect""}, {""type"": ""color"", ""value"": ""olive""}]}"),
("{""list"": [{""type"": ""color"", ""value"": ""red""}]}")
;

现在我需要从所有行中选择具有type = color 的所有对象。

我想看看这个输出:

id  extracted_value
1   {"type": "color", "value": "red"}
1   {"type": "color", "value": "green"}
2   {"type": "color", "value": "olive"}
3   {"type": "color", "value": "red"}

得到这个也很好:

id  color
1   red
1   green
2   olive
3   red

我无法更改数据库或 JSON。

我使用的是 MySQL 5.7

我目前的解决方案

我的解决方案是用一些索引集交叉连接表,然后提取 JSON 数组的所有元素。

我不喜欢它,因为一个数组中可能的对象计数很大,它需要所有索引直到最大一个。它使查询变慢,因为它不会在到达数组末尾时停止计算 JSON 值。

SELECT 
    test.id,
    JSON_EXTRACT(test.json_list, CONCAT('$.list[', ind.ind, ']')),
    ind.ind
FROM
    test
CROSS JOIN
    (SELECT 0 AS ind UNION ALL SELECT 1 AS ind UNION ALL SELECT 2 AS ind) ind
WHERE
    JSON_LENGTH(json_list, "$.list") > ind.ind
    AND JSON_EXTRACT(json_list, CONCAT('$.list[', ind.ind, '].type')) = "color";

通过更改JSON_EXTRACT 路径很容易只获取值。但是有没有更好的方法?

编辑

  • 添加了对 json_list.list 长度的检查。在这种情况下,这会过滤掉 67% 的派生表行。

【问题讨论】:

  • 5.7 无能为力。我会使用数组的长度来限制 JOIN:json_length(json_list->'$.list') > ind.ind
  • @PaulSpiegel 检查长度应该会有所帮助。谢谢你。将编辑我的解决方案。

标签: mysql arrays json mysql-5.7


【解决方案1】:

所以目前最好的解决方案是我的:

SELECT 
    test.id,
    JSON_EXTRACT(test.json_list, CONCAT('$.list[', ind.ind, ']')),
    ind.ind
FROM
    test
CROSS JOIN
    (SELECT 0 AS ind UNION ALL SELECT 1 AS ind UNION ALL SELECT 2 AS ind) ind
WHERE
    JSON_LENGTH(json_list, "$.list") > ind.ind
    AND JSON_EXTRACT(json_list, CONCAT('$.list[', ind.ind, '].type')) = "color";

【讨论】:

    【解决方案2】:
    SELECT JSON_EXTRACT(json_list, '$.list[*]')
    FROM `test`
    where JSON_CONTAINS(json_list, '{"type":"color"}', '$.list')
    

    【讨论】:

    • Thiw 将为符合条件的行提供 json 数组:例如,它将提供 3 行而不是 4 行。每个结果将包含所有 json 数组元素。这不是所需要的
    • 你能提供这个解决方案为什么回答这个问题吗?
    • 这很有帮助,为什么没有人支持这个答案?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    相关资源
    最近更新 更多