MySQL - 搜索 JSON 数据列
Posted
技术标签:
【中文标题】MySQL - 搜索 JSON 数据列【英文标题】:MySQL - Search JSON data column 【发布时间】:2019-08-02 09:25:03 【问题描述】:我有一个 mysql 数据库列,其中包含 JSON 数组编码的字符串。我想搜索“Elapsed”值大于特定数字的 JSON 数组,并返回找到该值的对象的相应 TaskID 值。我一直在尝试使用 JSON_SEARCH、JSON_CONTAINS 和 JSON_EXTRACT 函数的组合,但没有得到想要的结果。
[
"TaskID": "TAS00000012344",
"Elapsed": "25"
,
"TaskID": "TAS00000012345",
"Elapsed": "30"
,
"TaskID": "TAS00000012346",
"Elapsed": "35"
,
"TaskID": "TAS00000012347",
"Elapsed": "40"
]
参考上面的 JSON,如果我搜索“Elapsed”>“30”,那么将返回 2 条记录
'TAS00000012346'
'TAS00000012347'
我正在使用 MySQL 5.7.11 版,并且是查询 json 数据的新手。任何帮助,将不胜感激。谢谢
【问题讨论】:
你能展示一下你的表结构吗?如果我没记错的话,您必须将列定义为实际 JSON 类型,或者为了使用这些函数,您至少需要将 varchar 字段转换为 json 类型,请看这里:dev.mysql.com/doc/refman/5.7/en/json.html#json-paths “我有一个 MySQL 数据库列,其中包含 JSON 数组编码的字符串” 为什么? 包含 JSON 数据的列只是一个“文本”数据类型。无论数据类型如何,JSON 函数都可以正常工作。可能没有他们应该/可能的那么好。 【参考方案1】:在 MySQL 8.0 之前,没有简单的方法将 JSON 数组转换为记录集(即,函数 JSON_TABLE()
尚不可用)。
因此,无论哪种方式,我们都需要手动遍历数组以提取相关数据(使用JSON_EXTRACT()
)。这是一个使用内联查询生成数字列表的解决方案;另一个经典的方法是使用数字表。
假设一个名为 mytable
的表具有一个名为 js
的列,其中包含 JSON 内容:
SELECT
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].TaskID')) TaskID,
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) Elapsed
FROM mytable t
CROSS JOIN (
SELECT 0 idx
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
) n
WHERE JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) * 1.0 > 30
注意:在WHERE
子句中,* 1.0
操作用于强制转换为数字。
Demo on DB Fiddle 与您的示例数据:
| TaskID | Elapsed |
| -------------- | ------- |
| TAS00000012346 | 35 |
| TAS00000012347 | 40 |
【讨论】:
专线小巴,非常感谢。它确实有效。你能解释一下“n.idx”的作用吗? @JNicolls:欢迎!n
是生成数字列表的子查询的别名,idx
是包含数字本身的列。所以n.idx
产生0
,然后是1
,以此类推。【参考方案2】:
是的,你绝对可以在 mysql 中使用 JSON_EXTRACT() 函数。
让我们获取一个包含 JSON 的表(此处为表 client_services
):
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | "quota": 1,"data_transfer":160000 |
| 101 | 1000 | "quota": 2,"data_transfer":800000 |
| 102 | 1000 | "quota": 3,"data_transfer":70000 |
| 103 | 1001 | "quota": 1,"data_transfer":97000 |
| 104 | 1001 | "quota": 2,"data_transfer":1760 |
| 105 | 1002 | "quota": 2,"data_transfer":1060 |
+-----+-----------+--------------------------------------+
现在假设我们想要所有有 quota>1 的人的 client_id,然后使用这个查询:
SELECT
id,client_id,
JSON_EXTRACT(service_values, '$.quota') AS quota
FROM client_services
WHERE JSON_EXTRACT(service_values, '$.quota') > 1;
因此它会导致:
+-----+-----------+-------+
| id | client_id | quota |
+-----+-----------+--------
| 101 | 1000 | 2 |
| 102 | 1000 | 3 |
| 104 | 1001 | 2 |
| 105 | 1002 | 2 |
+-----+-----------+-------+
希望这会有所帮助!
【讨论】:
以上是关于MySQL - 搜索 JSON 数据列的主要内容,如果未能解决你的问题,请参考以下文章
如何检查 MySQL JSON 列是不是包含 laravel 中的值?