Chr*_*isP 5 mysql sql json mysql-8.0
我有一个 MySQL 8.0.22 JSON 列,其中包含带有事先未知的键的对象:
'{"x": 1, "y": 2, "z": 3}'
'{"e": 4, "k": 5}'
Run Code Online (Sandbox Code Playgroud)
我想用来JSON_TABLE将这些值扩展为包含键值对的多行:
| 钥匙 | 价值 |
|---|---|
| X | 1 |
| y | 2 |
| z | 3 |
| e | 4 |
| k | 5 |
当然,困难在于密钥不是先验已知的。我想出的最好的办法是...
'{"x": 1, "y": 2, "z": 3}'
'{"e": 4, "k": 5}'
Run Code Online (Sandbox Code Playgroud)
这感觉很奇怪,因为它使用两个JSON_TABLE调用,对值和键进行交叉连接,然后保持对齐。我想找到一个像这样的更简单的查询......
SET @json_doc = '{"x": 1, "y": 2, "z": 3}';
SELECT a.seq, b.k, a.v
FROM
JSON_TABLE(
@json_doc,
"$.*"
COLUMNS(
seq FOR ordinality,
v INT PATH "$"
)
) AS a,
JSON_TABLE(
JSON_KEYS(@json_doc),
"$[*]"
COLUMNS(
seq FOR ordinality,
k CHAR(1) PATH "$"
)
) AS b
WHERE a.seq = b.seq;
Run Code Online (Sandbox Code Playgroud)
我知道这个问题可能可以通过 CTE 或数字表和 来解决JSON_EXTRACT。但是,如果可能的话,我想找到一些高性能且可读的东西。
您可以通过使用窗口函数来使用enumarete,ROW_NUMBER()同时通过使用确定键值JSON_KEYS(),然后使用JSON_EXTRACT()我们得到的数组中提取相应的键,例如
WITH k AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY `jsdata` ORDER BY value DESC) AS rn,
JSON_KEYS(`jsdata`) AS jk
FROM `tab` AS t
JOIN JSON_TABLE(`jsdata`,'$.*' COLUMNS (value INT PATH '$')) j
)
SELECT JSON_UNQUOTE(JSON_EXTRACT(jk, CONCAT('$[',rn-1,']'))) AS "key",
value
FROM k
Run Code Online (Sandbox Code Playgroud)
或者使用以下查询更简单
SELECT JSON_UNQUOTE(
JSON_EXTRACT(JSON_KEYS(`jsdata`),
CONCAT('$[',
ROW_NUMBER() OVER(PARTITION BY `jsdata` ORDER BY value DESC)-1,
']'))
) AS "key", value
FROM `tab` AS t
JOIN JSON_TABLE(`jsdata`,'$.*' COLUMNS (value INT PATH '$')) j
Run Code Online (Sandbox Code Playgroud)