如何使用 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 数组?