用于确定 JSON 值是不是包含指定属性的 SQL 查询
Posted
技术标签:
【中文标题】用于确定 JSON 值是不是包含指定属性的 SQL 查询【英文标题】:SQL query to determine if a JSON value contains a specified attribute用于确定 JSON 值是否包含指定属性的 SQL 查询 【发布时间】:2017-02-05 12:22:53 【问题描述】:我有一个表,其中有一列用于存储每行的 JSON 值。目前,这些还没有标准化。我想最终将这些 JSON 值中的每一个在属性的数量和标题上标准化。是否可以使用查询来确定每个 JSON 值是否包含指定的属性?
例如,下面是一些 JSON 值的样子:
"name":"Item 1","cost":"4.99"
"name":"Item 2"
"name":"Item 3","cost":""
"name":"Item 4"
我该怎么做:
确定哪些行具有“成本”属性(项目 1 和 3) 确定哪些行没有“成本”属性(项目 2 和 4) 确定哪些行为“成本”属性(第 1 项)设置了值谢谢!这是我第一次询问(至少最近)所以非常感谢任何帮助!
【问题讨论】:
解析字段的字符串值,寻找cost
属性。
【参考方案1】:
mysql 不解析 JSON 数组。它将它们视为字符串。所以你必须使用LIKE
。
【讨论】:
MySQL 5.7 内置 JSON 函数。 你应该展示LIKE
模式来实现他的条件。【参考方案2】:
我假设您使用的是 MySQL 5.7,它添加了 JSON
数据类型。使用JSON_EXTRACT(colname, '$.cost')
访问cost
属性。它将是NULL
,如果没有这样的属性。
WHERE JSON_EXTRACT(colname, '$.cost') IS NOT NULL
WHERE JSON_EXTRACT(colname, '$.cost') IS NULL
WHERE JSON_EXTRACT(colname, '$.cost') != ''
如果 JSON 中的值为null
,它也将是NULL
;如果需要区分这种情况,请看Can't detect null value from JSON_EXTRACT
【讨论】:
令人遗憾的是,我无法区分属性不存在与属性存在,但没有价值。不过,这非常接近,并且会对我有很大帮助。谢谢! 您的 JSON 数据中是否都有"cost": null
?
一些行有一个“成本”属性,但不是全部。我的目标是尝试快速整理出没有它的行,这样我就可以添加一个,然后使用 JSON 修改函数来更新那部分,而不是更新整个 JSON 字符串。
应该可以。您唯一无法区分的是"cost": null
中的无成本属性。 "cost": ""
仍然可以区分。
你的回答其实是准确的。 MySQL 确实将 SQL NULL
与 JSON 的 null
区分开来。您可以删除最后一条语句。有关详细信息,请参阅此答案:***.com/a/41172432/1128918【参考方案3】:
实际上,您可以通过将JSON_EXTRACT
结果与自身进行比较来做到这一点:
WHERE JSON_EXTRACT(colname, '$."cost"') = JSON_EXTRACT(colname, '$."cost"')
如果您的 JSON 列中没有相应的键,这将以某种方式为“假”/null。
通过这种方式,您可以找到所有具有您要搜索的键的条目。如果您想要所有没有密钥的条目,您就不能使用 NOT 运算符。你必须这样做:
SELECT * FROM tablename WHERE id NOT IN (SELECT id FROM tablename WHERE WHERE JSON_EXTRACT(colname, '$."cost"') = JSON_EXTRACT(colname, '$."cost"'))
我知道它看起来像伏都教,但它似乎有效。
【讨论】:
【参考方案4】:如果只需要检查json键是否存在,可以使用JSON_CONTAINS_PATH。我希望它比 JSON_EXTRACT 更快。
mySQL 8.0 docs
例子:
我在数据库中有一个权限列。结构如下:
"users":
"user1" : "rw",
"user2" : "r"
,
"groups":
"root": "rw",
"anotherGroup" : "r"
如果我想获取所有具有根组的项目(关于实际权限),我使用这个:
SELECT * FROM `filesystem_folders` where JSON_CONTAINS_PATH(permissions, 'one', '$.groups.root');
我在上面的 select 之间做了一个非常简单的时间比较,耗时 12.90s(10000 次读取)。与使用 JSON_EXTRACT
的以下选择相比 SELECT * FROM `filesystem_folders` where JSON_EXTRACT(permissions, '$.groups.root') IS NOT NULL;
耗时 15.13 秒。所以,差别很小。
【讨论】:
【参考方案5】:如果您使用的是没有 JSON 函数的 MySQL(5.7 之前),或者想要检查列表中的任何标签,或者不可预测的嵌套 JSON。
这是一个如何使用LIKE
的示例:
SELECT case when colname like '%cost%' then 1 else 0 end as has_cost,
case when colname like '%cost":""%' then 1 else 0 end as has_cost_with_no_value
FROM tablename
【讨论】:
MySQL 支持 JSON 查询,这对你需要做的事情来说太过分了。查看其他答案。以上是关于用于确定 JSON 值是不是包含指定属性的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章
json序列化后的是字符串,不是二进制。是字符串!!!确定不是二进制!!!