【问题标题】:MySQL JSON extract a single value by idMySQL JSON 按 id 提取单个值
【发布时间】:2017-12-31 17:05:25
【问题描述】:

我在extra_fields 列中有一个带有 JSON 数组的数据库。我需要通过 id 提取一个值。

JSON 看起来像这样,尽管每行的对象数量是随机的:

[
{"id":"1","value":"48768"},
{"id":"2","value" ["String","http:someurl"]},
{"id":"5","value":"somevalue"},
{"id":"6","value":""},
{"id":"8","value":"Op-Ed"},
{"id":"9","value":"8111,13498,15408"},
{"id":"10","value":"30"},
{"id":"11","value":"This is the target string"}
]

我可以提取一个 id 数组:

SELECT extra_fields->>"$[*].id"  FROM esqt7_k2_items;

我可以提取一个值数组:

SELECT extra_fields->>"$[*].value"  FROM esqt7_k2_items;

我可以在第 n 个零序对象位置提取单个值:

SELECT extra_fields->>"$[2].value"  FROM esqt7_k2_items;

但问题是对象的数量可变,我特别需要对象 id = 11 的值。JSON_EXTRACT 似乎不支持过滤,因为 JSONPATH 的每个变体似乎都失败了。 $..[?(@.id=11)].value 作为 JSONPATH 工作,但是这个(以及许多变体)失败了:

SELECT extra_fields->"$.[?(@.id=11)].value" FROM esqt7_k2_items; #FAILS

这是一个迁移项目,JSON 内容正是 Joomla 选择实现其额外字段的方式。如果你问我,有点痛苦。

【问题讨论】:

    标签: mysql json mysql-json


    【解决方案1】:

    您可以考虑的一个选项(注意性能问题):

    mysql> SELECT VERSION();
    +-----------+
    | VERSION() |
    +-----------+
    | 5.7.19    |
    +-----------+
    1 row in set (0.00 sec)
    
    mysql> DROP TABLE IF EXISTS `esqt7_k2_items`;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> CREATE TABLE IF NOT EXISTS `esqt7_k2_items` (
        ->   `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        ->   `extra_fields` JSON NOT NULL
        -> );
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO `esqt7_k2_items`
        ->   (`extra_fields`)
        -> VALUES
        ->   ('
        '>     [
        '>       {"id": "1", "value": "48768"},
        '>       {"id": "2", "value": ["String","http:someurl"]},
        '>       {"id": "5", "value": "somevalue"},
        '>       {"id": "6", "value": ""},
        '>       {"id": "8", "value": "Op-Ed"},
        '>       {"id": "9", "value": "8111,13498,15408"},
        '>       {"id": "10", "value": "30"},
        '>       {"id": "11", "value": "This is the target string"}
        '>     ]
        '>   '),
        ->   ('
        '>     [
        '>       {"id": "1", "value": ""},
        '>       {"id": "9", "value": "ONE This is the target string"}
        '>     ]
        '>   '),
        ->   ('
        '>     [
        '>       {"id": "6", "value": ""},
        '>       {"id": "11", "value": "TWO This is the target string"}
        '>     ]
        '>   ');
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> SET @`search_id` := '11';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT `der`.`id`, `der`.`value`
        -> FROM (
        ->   SELECT
        ->     `id`,
        ->     JSON_UNQUOTE(
        ->       JSON_EXTRACT(`extra_fields`,
        ->         CONCAT((SELECT
        ->           JSON_UNQUOTE(
        ->             JSON_SEARCH(`extra_fields` ->> '$[*].id', 'one', @`search_id`)
        ->           )
        ->                 FROM `esqt7_k2_items` `esqt7_k2_items_in`
        ->                 WHERE `esqt7_k2_items_out`.`id` = `esqt7_k2_items_in`.`id`
        ->                ), ".value"
        ->         )
        ->       )
        ->     ) `value`
        ->   FROM `esqt7_k2_items` `esqt7_k2_items_out`
        -> ) `der`
        -> WHERE `der`.`value` IS NOT NULL;
    +----+-------------------------------+
    | id | value                         |
    +----+-------------------------------+
    |  1 | This is the target string     |
    |  3 | TWO This is the target string |
    +----+-------------------------------+
    2 rows in set (0.00 sec)
    

    db-fiddle

    【讨论】:

    • 这需要我一点时间来测试,但第一部分建议 extra_fields 需要输入 JSON 并以 id 作为查询的主键?
    • @Slam:表结构和列的数据类型是任意定义的。您可以根据需要进行修改和调整。
    【解决方案2】:

    我发现的最简单的方法

    对象id = 11的值

    它通过找到所需对象的正确“索引”,做一点 PHP。 首先,我们通过您的简单请求获取所有对象 ID:

    > SELECT extra_fields->>"$[*].id"  FROM esqt7_k2_items;
    

    然后在 PHP 中

    $rightIndex = array_search($ids, '11');
    

    然后你通过传递这个 $rightIndex 得到正确的对象:

    SELECT extra_fields->>"$[$rightIndex].value"  FROM esqt7_k2_items;
    

    简直太简单了!您可以在其他任何地方执行相同的操作,例如,当您需要更新数组中的对象或其值/值等时。 也就是说,干杯!

    【讨论】:

    • 不幸的是,我需要在 MySQL 而不是 PHP 中执行此操作。
    猜你喜欢
    • 1970-01-01
    • 2023-03-24
    • 2020-08-27
    • 2021-03-08
    • 1970-01-01
    • 2017-07-29
    • 2020-10-06
    • 1970-01-01
    • 2022-07-02
    相关资源
    最近更新 更多