如何使用 MySQL 查询 json 数组

Posted

技术标签:

【中文标题】如何使用 MySQL 查询 json 数组【英文标题】:How to use MySQL to query on json array 【发布时间】: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]');

我有两个要求:

    查找名称中包含“abc”且所有名称中包含“abc”的值大于120的行。即对于上表,选择id=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搜索功能。

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

【问题讨论】:

【参考方案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作为示范可能比较安全。 这个想法很有价值,我会用大规模数据验证其可行性,非常感谢。

以上是关于如何使用 MySQL 查询 json 数组的主要内容,如果未能解决你的问题,请参考以下文章

如何从 MySQL 的 JSON 数组中删除一个数字?

如何使用我的 MYSQL 数据库中的数据填充 JSON 数组?

如何在node.js中将json数组数据插入mysql?

MySQL如何索引JSON数组?

mysql数据库中某个字段存的是json数据,如何对json数据中的数据进行操作?

C++下如何将json数据存入mysql数据库