将 JSON "dictonary" 拆分为单独的行

Split JSON "dictonary" into separate rows

同事们。 我有一个像这样的 table:

id param1 param2 config
123 456 789 {"confToUse": "b", "configs": {"a": { "qwe": "rty" }, "b": { "asd", "fgh" } } }

小说明:配置在json 'dictionary' 属性 configs, configToUse 属性 点在配置上用这个键使用。

我的目标是获得新的 table,其中每一行都是一个单独的配置:

id name config
x_uniq a { "qwe": "rty" }
y_uniq b { "asd", "fgh" }

理想情况下,结果如下所示:

id param1 param2 use name config use_id
x_uniq 456 789 b a { "qwe": "rty" } y_uniq?
y_uniq 456 789 b b { "asd", "fgh" } y_uniq?

由于 mysql 版本原因我无法使用 JSON_TABBLE。只有 JSON_EXTRACT 左右。

此时只能这样做:

SELECT 
    JSON_EXTRACT(tbl.config, "$.configToUse"),
    JSON_EXTRACT(tbl.config, "$.configs") -- I think there has to be some SELECT
FROM 
    configs_table tbl
WHERE
    tbl.id = 123
;

并得到:

xxx yyy
b {"a": { "qwe": "rty" }, "b": { "asd", "fgh" } }

拜托,给我一些移动方式。

为此,您需要另一个 table(或子查询),它具有从 0 到 N 的整数,其中 N 是您可能拥有的最大配置数量。

为这些整数创建实用程序 table:

CREATE TABLE N ( N INT PRIMARY KEY );
INSERT INTO N (N) VALUES (0), (1), (2), (3), (4), (5);

或者按需生成 table 作为子查询:

SELECT ...
FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS N
...

有了这个,您可以进行交叉连接以获取 JSON 文档中的每个配置键。

这是一个演示:

SELECT
  t.param1, t.param2,
  JSON_UNQUOTE(JSON_EXTRACT(t.config, '$.confToUse')) AS `use`,
  t.name,
  JSON_EXTRACT(t.config, CONCAT('$.configs.', t.name)) AS config
FROM (
  SELECT c.param1, c.param2, c.config,
    JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(c.config->'$.configs'), CONCAT('$[',N.N,']'))) AS name
  FROM N CROSS JOIN configs_table c
) AS t
WHERE t.name IS NOT NULL;

输出:

+--------+--------+------+------+----------------+
| param1 | param2 | use  | name | config         |
+--------+--------+------+------+----------------+
|    456 |    789 | b    | a    | {"qwe": "rty"} |
|    456 |    789 | b    | b    | {"asd": "fgh"} |
+--------+--------+------+------+----------------+

我无法从你的问题中得知你是如何获得值 x_uniqy_uniq,所以我将把那部分解决方案留给你。

如果您认为此解决方案复杂而困难,请将其作为示例,说明为什么在 MySQL 中使用 JSON 会导致很多麻烦和耗时的工作。在数据库之上实现伪数据库既不方便也不正确。这有时称为 Inner-Platform Effect 反模式。