MySQL从行中任意长的字符串数组中获得不同的值

时间:2018-08-09 17:09:00

标签: mysql arrays json mysql-5.7

我有一个带有JSON列的表,我们称它为json_data,列内容看起来像...

[{ "data": { ... }, "name": "name_1" }, { "data": { ... }, "name": "name_2" }]
[{ "data": { ... }, "name": "name_2" }]
[{ "data": { ... }, "name": "name_3" }, { "data": { ... }, "name": "name_5" }]
[{ "data": { ... }, "name": "name_4" }]

...而且我希望能回来

["name_1", "name_2", "name_3", "name_4", "name_5"]

或类似的东西。我可以使用JSON_EXTRACT轻松获得每一行的名称字段集...

SELECT JSON_EXTRACT(json_data, "$**.name") FROM my_table;

...所以现在我有一些行,每个行包含一个逗号分隔的字符串数组,可以使用GROUP_CONCAT合并它们...

SELECT REPLACE(REPLACE(GROUP_CONCAT(names SEPARATOR ','), '[', ''), ']', '')
FROM (
    SELECT JSON_EXTRACT(json_data, '$**.name') as names 
    FROM my_table 
    WHERE json_data <> '' -- exclude empty entries
    LIMIT 10) x -- test on sample size as the table is quite large
ORDER BY NULL; -- get names from all rows

...在这一点上,我希望将所有数据作为逗号分隔的字符串放在一行中...

"name_1","name_2","name_2","name_3","name_4","name_5"

,但有重复项(许多重复项)。

使用它并在其上执行不同的操作似乎应该很容易,但是到目前为止,我仍无法弄清楚如何将字符串拆分为所有元素并执行不同的操作。 SUBSTRING_INDEX似乎是我所需要的,但这只能得到单个元素...任何帮助都将受到赞赏!

1 个答案:

答案 0 :(得分:0)

在现代版本的MySQL(> = 8.0.4)中,查询相对简单:

SELECT
  GROUP_CONCAT(
    DISTINCT JSON_QUOTE(`der`.`names`)
  ) `names`
FROM
  `my_table`,
  JSON_TABLE(`my_table`.`json_data`,
    '$[*]' COLUMNS(
      `names` VARCHAR(10) PATH '$.name'
    )
  ) `der`
ORDER BY
  `names`;

请参见db-fiddle

但是,在旧版本中,并不是那么简单,一种选择可能是使用临时表和准备好的语句:

SET @`ddl` := CONCAT('INSERT INTO `my_table` VALUES ',
  (SELECT
    GROUP_CONCAT(
      REPLACE(
        REPLACE(
          REPLACE(
            `json_data` -> '$**.name',
          '[', '('),
        ']', ')'),
      ',', '),(')
    )
  FROM
    `my_table`
  )
);

请参见Rextester

无论如何,请记住5.1.7 Server System Variables::group_concat_max_len