【问题标题】:How to replace keys of a JSON values in a column using the values of another column in a different table?如何使用不同表中另一列的值替换列中 JSON 值的键?
【发布时间】:2019-08-22 17:48:12
【问题描述】:

我在 mysql 架构中有两个表,我们称它们为 sitesfields。站点表为以下架构:

create table if not exists sites
(
    id int auto_increment
        primary key,
    collection_id int null,
    name varchar(255) null,
    properties text null,
)
;

并且字段具有以下架构

create table fields
(
    id int auto_increment
        primary key,
    collection_id int null, 
    name varchar(255) null,
    code varchar(255) null,
)
;

这两个表可以在collection_id 列上连接。 sites 表将 json 数据存储在 properties 列中,json 对象的键是字段表中 id 列的值。例如,这是一个可以在 properties 中找到的示例 json专栏

{"1281":"Type A","1277":4}

上面json中的key是字段中记录的id。

+---------+--------------+--------------+
|id       |  name        |   code       |
+---------------------------------------+
| 1277    |  Years       |  Yr          |
+---------------------------------------+
| 1281    | Type         |  Ty          |
+---------+--------------+--------------+


现在,我想输出属性 json,其中键被字段名称而不是 id 值替换。使用上面的示例,输出应如下所示:

{"Type": "Type A", "Years": 4}

到目前为止,我已经尝试过以下方法

select JSON_OBJECT(fd.name, JSON_EXTRACT(st.properties, concat('$."', fd.id, '"'))) as prop  
from sites as st join fields as fd on fd.collection_id = st.collection_id where st.collection_id = 145 and

JSON_EXTRACT(st.properties, concat('$."', fd.id, '"')) is not  null ;

但是,这会为每个字段而不是站点生成 json 对象。

它输出如下内容:

 +----------------------------+
 |        prop                |
+-----------------------------+
 |  {"Type": "Type A"}        |
 |                            |
 +----------------------------+
 |   {"Type": "Type B"}       |
 |                            |
 +-----------------------------+
 |                            |
 |    {"Year": 4}             |
 |                            |
 +----------------------------+

如何修改上述代码以获得所需的输出?或者有没有更好的解决方案?

【问题讨论】:

  • 一般来说,将复杂字段存储在 JSON 中并不是一个很好的理由。也有例外,但这通常是一种反模式。你不能把它分解成字段,所以这是一个标准查询吗?如果您必须将其存储为 JSON,也许 JSON 数据类型会更好地为您服务。

标签: mysql sql json


【解决方案1】:

我使用group_concat 函数将每个站点的结果按站点ID 分组后将它们连接成一个,从而得出了解决方案。这是查询:

select concat('{' ,group_concat(concat('\"', cast(fd.code as char(50)), '\":' , JSON_EXTRACT(st.properties, concat('$.\"', fd.id, '\"')))), '}') as prop , st.id as site 
from sites as st join fields as fd on fd.collection_id = st.collection_id 
where st.collection_id = 145 and
JSON_EXTRACT(st.properties, concat('$."', fd.id, '"')) is not  null
group by st.id

注意:此解决方案假定您使用的是 MySQL 5.7+ 版本,因为那是引入 JSON_EXTRACT 函数的时候。如果您使用的是较低版本,请使用此 answer 中的 UDF 替代 JSON_EXTRACT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2021-04-24
    相关资源
    最近更新 更多