mysql - MySQL 8:使用 JSON_TABLE 解压缩任意 JSON 键值对
问题描述
我有一个 json 有效负载,其中包含我想要提取并插入到表中的任意键-> 值对。
我不知道高级键名,因此需要使用 MySQL 查询从 JSON 中动态提取它们。
任何帮助将不胜感激,但请:-
- 不要建议通过将属性重构为具有一致键的对象来重新设计架构
- EG
{"myatt1": "value1"}
成[{ name: "myatt1", "value": "value1 }]
- EG
- 不建议稍后在演示文稿中这样做;javascript,python,java等。
- 我想知道如何使用 MySQL 8 的 JSON 函数来做到这一点。
架构 (MySQL v8.0)
DROP TABLE IF EXISTS `objects`;
CREATE TABLE IF NOT EXISTS `objects` (
`id` SERIAL,
`payload` JSON NOT NULL
);
INSERT INTO `objects`
(`payload`)
VALUES
(
'[
{
"name": "object #1",
"attributes": {
"myatt1": "value1",
"myatt2": "value2"
}
},{
"name": "object #2",
"attributes": {
"another thing": "another value",
"random tag": "random value"
}
}
]'
);
查询 #1
SELECT `j`.*
FROM
`objects`,
JSON_TABLE(
`payload`,
'$[*]'
COLUMNS(
`objectid` FOR ORDINALITY,
`objectname` VARCHAR(50) PATH '$.name',
NESTED PATH '$."attributes".*' COLUMNS (
`attribute_id` FOR ORDINALITY,
`attribute_name` VARCHAR(50) PATH '$', /* Dont know how to do this */
`attribute_value` VARCHAR(50) PATH '$'
)
)
) `j`;
到目前为止我得到了什么(第 4 列是错误的)
| objectid | objectname | attribute_id | attribute_name | attribute_value |
| -------- | ---------- | ------------ | -------------- | --------------- |
| 1 | object #1 | 1 | value1 | value1 |
| 1 | object #1 | 2 | value2 | value2 |
| 2 | object #2 | 1 | random value | random value |
| 2 | object #2 | 2 | another value | another value |
要求的结果
| objectid | objectname | attribute_id | attribute_name | attribute_value |
| -------- | ---------- | ------------ | -------------- | --------------- |
| 1 | object #1 | 1 | myatt1 | value1 |
| 1 | object #1 | 2 | myatt2 | value2 |
| 2 | object #2 | 1 | random value | random value |
| 2 | object #2 | 2 | another thing | another value |
解决方案
一种选择是使用JSON_KEYS和JSON_EXTRACT:
SELECT
`der`.`objectid`,
`der`.`objectname`,
`der`.`attribute_id`,
`der`.`attribute_name`,
`der`.`attribute_value`
FROM (
SELECT
`j`.`objectid`,
`j`.`objectname`,
`j`.`attribute_id`,
`j`.`attribute_value`,
JSON_UNQUOTE(
JSON_EXTRACT(
JSON_KEYS(
`payload`,
CONCAT(
'$[', `j`.`objectid` - 1, '].attributes'
)
),
CONCAT(
'$[', `j`.`attribute_id` - 1, ']'
)
)
) `attribute_name`
FROM
`objects`,
JSON_TABLE(
`payload`,
'$[*]'
COLUMNS (
`objectid` FOR ORDINALITY,
`objectname` VARCHAR(50) PATH '$.name',
NESTED PATH '$.attributes.*' COLUMNS (
`attribute_id` FOR ORDINALITY,
`attribute_value` VARCHAR(50) PATH '$'
)
)
) `j`
) `der`;
请参阅db-fiddle。
推荐阅读
- vuejs2 - Vue 3 文件上传验证无法运行我的项目
- node.js - 如何使用 discord.js 在我的代码上解决此错误?:TypeError:无法读取未定义的属性“客户端”
- docker - 无法在 pod 内发送 http post 请求
- sql - 如何访问相关子查询中的列
- node.js - Nginx 拦截 nodejs 端点导致错误
- kubernetes - 通过“port”而不是“nodePort”访问的 LoadBalancer 服务
- c++ - 使用 assemply 文件作为操作函数的 4x4 键盘计算器程序。Mbed 使用 nucleo f401re 微控制器
- java - Java Hadoop MapReduce 按不同字段分组
- python - 并非所有行都是从我的 CSV 文件中打印的
- c - 如何在c程序中的数组中插入多个元素?