存储动态列的结果集(行列互转)--java、mybatis、orcale

发布时间 2023-03-29 13:33:13作者: Cloong

业务上需要存储动态列的数据 通过行列互转的方式实现

数据库中动态列的几种设计思路

  • 使用数据库DDL进行动态创建

  • 使用数据库预留字段(宽表)

  • 使用数据库中的json数据类型

  • 使用非关系型数据库(MongoDB等)

这是网上给出的几个基本思路,考虑到我们业务上的功能不太适合这些方法,所有最后选择通过行列互转的方式实现。

数据库设计

数据库使用了4个字段,key是原表中的列名,value是对应的值,sort有两个作用,排序和分组,row_id用于关联主表。数据库结构如下表table

名称 类型 注释
COL_KEY VARCHAR2(50) 列名(key)
COL_VALUE VARCHAR2(255) 列值(value)
ROW_ID VARCHAR2(50) 所属主表id
SORT NUMBER 排序

行转列(存储)

第一步是将动态列的结果集存储起来

列名1 列名2 列名3 ... 列名N
a b c ... e
1 2 3 ... 5
A B C ... E
6 7 8 ... 10

结果集返回的数据是List<Map> 结构,这里不做太多赘述了

直接上代码

//存入列表(列转行)
List<Table> list= new ArrayList<>();//新建一个table类型的集合
long index = 1;//排序索引
for (Map map : list) { //list是返回的结果集,直接遍历
    // 通过keySet方法获取list中一个map的所有key
    Set<String> keySet = map.keySet(); 
    for (String s : keySet) { //继续遍历所有key
        //新建临时对象
        Table table = new Table();
        table.setColKey(s);//设置属性Key
        //设置属性value,通过get(key)的方式,同时将value的类型都处理成String
        table.setColValue(String.valueOf( map.get(s)));
        table.setSort(index);//设置分组条件的同时还能排序
        table.setRowId(“自定义”);//根据传过来的值设置属于那个主表
        list.add(table);//加入集合中
    }
    index++;
}

列转行(显示)

假设上一步已经将数据存入table表中

col_key col_value row_id sort
列名1 a id 1
列名1 a id 1
列名1 a id 1
列名1 a id 1
列名1 a id 1
列名1 a id 1
列名1 a id 1
列名1 a id 1
1 2 3 ...
A B C ...
6 7 8 ...

存完之后下一步就该显示了,虽然我们是通过列的方式存的,但是我们显示的时候还是应该将列转换成行来显示,就和存之前的结果集一样

我用的数据库是Oracle,因此有两种方式来实现

SQL通用方式

select sort,
MAX(case col_key when '状态' then col_value  end) as AAA,
MAX(case col_key when '创建者' then col_value  end) as AAA,  
MAX(case col_key when '编号' then col_value  end) as AAA,
MAX(case col_key when '类型' then col_value  end) as AAA
from monitor_detail 
where monitor_id = 235 
group by sort order by sort