使用mysql的 JSON_OBJECTAGG 聚合函数。
官网地址:
https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-objectagg
用数据字典来举例子
下面4张表:
dict存放的是类型,例如:基本信息,主芯片。
item 存放的是代表行的记录
head 存放的是表头 如基本信息的表头或者主芯片的表头
detail 存放的是具体数据。这个表有点不好的地方就是每个属性都得一行。detail数据会膨胀得很厉害,所以数据多谨慎使用。
如果跟我一样直接通过类型就能准确定位少量数据还是没啥问题的。
dict表和对应的数据
item表和对应的数据
head表和对应的数据
detail表和对应的数据
查询的sql ,实际怎么查询按自己需求来。
-- 查询对应表头的数据
SELECT t.id ,t.name , JSON_OBJECTAGG(d.attribute,d.attribute_value) attribute FROM
`bd_dict` dt
LEFT JOIN `bd_dict_item` t ON t.dict_id = dt.id
LEFT JOIN `bd_dict_item_detail` d ON d.item_id = t.id
WHERE dt.id =1 -- 查询同一类型下的 ,在我的需求中dt表的id其实相当与一张表
GROUP BY t.id
;
-- 查询表头
SELECT dt.dict_code ,dt.dict_name , JSON_OBJECTAGG(h.attribute,h.attribute_name) head_info FROM
`bd_dict` dt
LEFT JOIN `bd_dict_item_head` h ON h.dict_id = dt.id
WHERE dt.id =1
GROUP BY dt.dict_name
;
查询的表头是个json。 因为是动态列,所以表头信息也得返回给前端,表头信息和detail的数据使用相同的key来对应关系
对应的java对象
class ItemHead{
String dictCode;
String dictName;
String headInfo; // json 类型可以使用String 来接受
}
detail查询的结果。
如果需要对json的查询结果进行过滤,可以参考官方文档的json查询api。这里就不列举了。
虽然没有实现每个属性都对应一列,但这也算一个列转行对象。
class Phone{
String id;
String name;
// 示例假代码 类似这种,实际是String类型的 JSON 数据;
Attribute attribute ; // ===> String attribute
}
跟下面这种差别不是很大
class Phone{
String id;
String name;
String cpuNum;
String cpuBrand;
}
下面是执行计划,其他测试暂时没做,空了看看这种sql效率会如何
每个item_head 表可以根据item 的id ,使用javaassint 生成一个POJO类,作为参数接受。也可以直接使用JSON 工具。
以上就是mysql行转列的实现。
跟网上其他动态列例子一样。
都使用函数实现,只是这里使用的是json的函数,可以不需要在sql中写固定表头,
网上也有存储过程的实现,具体没怎么看,看各自需求。
sql文件自取地址