【问题标题】:How to use MySQL to query on json array如何使用 MySQL 查询 json 数组
【发布时间】:2022-01-23 02:09:27
【问题描述】:

我有一张如下图的表格:

CREATE TABLE IF NOT EXISTS `tb_test` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `content` json NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `tb_test` (`id`, `content`) VALUES (1, '[{"name": "vabcx", "value": 100}, {"name": "uabcw", "value": 150}, {"name": "xxx", "value": 110}]');
INSERT INTO `tb_test` (`id`, `content`) VALUES (2, '[{"name": "jabcl", "value": 130}, {"name": "xabcf", "value": 150}, {"name": "uuu", "value": 110}]');
INSERT INTO `tb_test` (`id`, `content`) VALUES (3, '[{"name": "pabcg", "value": 100}, {"name": "qabct", "value": 100}, {"name": "hhh", "value": 300}]');

我有两个要求:

  1. 查找名称中包含“abc”且所有名称中包含“abc”的值大于120的行。即对于上表,选择id=2的行。
  2. 查找名称包含“abc”且名称中至少有一个包含“abc”的值大于120的行。即,对于上表,选择id=1和id=2的行。

我尝试了下面的sql,但是因为name和value是分开处理的,所以3行都被选中了。

mysql> SELECT * FROM tb_test WHERE content->'$**.name' LIKE '%abc%'and content->'$**.value' > 120;
+----+---------------------------------------------------------------------------------------------------+
| id | content                                                                                           |
+----+---------------------------------------------------------------------------------------------------+
|  1 | [{"name": "vabcx", "value": 100}, {"name": "uabcw", "value": 150}, {"name": "xxx", "value": 110}] |
|  2 | [{"name": "jabcl", "value": 130}, {"name": "xabcf", "value": 150}, {"name": "uuu", "value": 110}] |
|  3 | [{"name": "pabcg", "value": 100}, {"name": "qabct", "value": 100}, {"name": "hhh", "value": 300}] |
+----+---------------------------------------------------------------------------------------------------+

另外,对于需求2,我不想使用下面的sql,因为以后可能会有$[4],$[5]......。

SELECT * FROM tb_test WHERE content->'$[0].name' LIKE '%abc%'AND content->'$[0].value' > 120 OR content->'$[1].name' LIKE '%abc%'AND content->'$[1].value' > 120 OR content->'$[2].name' LIKE '%abc%'AND content->'$[2].value' > 120;

我也知道将内容存储为下表可以解决问题。

CREATE TABLE IF NOT EXISTS `tb_test01` (
  `ass_id` bigint(20) unsigned NOT NULL COMMENT 'associated ID',
  `name` VARCHAR(32) NOT NULL,
  `value` int(11) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

但我想知道如何使用 sql 和 json,或者任何其他好的方法来解决我的问题。

我从here学到了一些json搜索功能。

期待您的帮助,提前感谢您。

【问题讨论】:

    标签: mysql arrays json search


    【解决方案1】:

    您可以使用 JSON_TABLE 将名称/值对放入行和列中:

    select id, j.* from tb_test cross join json_table(content, '$[*]' columns (
      name varchar(20) path '$.name', 
      value int path '$.value')) as j;
    +----+-------+-------+
    | id | name  | value |
    +----+-------+-------+
    |  1 | vabcx |   100 |
    |  1 | uabcw |   150 |
    |  1 | xxx   |   110 |
    |  2 | jabcl |   130 |
    |  2 | xabcf |   150 |
    |  2 | uuu   |   110 |
    |  3 | pabcg |   100 |
    |  3 | qabct |   100 |
    |  3 | hhh   |   300 |
    +----+-------+-------+
    

    然后你可以使用WHERE 子句来选择你想要的行。

    【讨论】:

    • JSON是一个数组,对象的位置可能需要,所以添加rowno FOR ORDINALITY作为示范可能比较安全。
    • 这个想法很有价值,我会用大规模数据验证其可行性,非常感谢。
    猜你喜欢
    • 2018-04-18
    • 1970-01-01
    • 2017-05-26
    • 2022-01-07
    • 2019-02-07
    • 1970-01-01
    • 2021-01-04
    • 2013-06-29
    • 2016-12-12
    相关资源
    最近更新 更多