返回顶部
首页 > 资讯 > 数据库 >Mysql纵表转换为横表的方法及优化教程
  • 875
分享到

Mysql纵表转换为横表的方法及优化教程

2024-04-02 19:04:59 875人浏览 独家记忆
摘要

1、纵表与横表 纵表:表中字段与字段的值采用key—value形式,即表中定义两个字段,其中一个字段里存放的是字段名称,另一个字段中存放的是这个字段名称代表的字段的值。 例如,下面这

1、纵表与横表

纵表:表中字段与字段的值采用key—value形式,即表中定义两个字段,其中一个字段里存放的是字段名称,另一个字段中存放的是这个字段名称代表的字段的值。

例如,下面这张ats_item_record表,其中field_code表示字段,后面的record_value表示这个字段的值

优缺点:

横表:表结构更加的清晰明了,关联查询的一些sql语句也更容易,方便易于后续开发人员的接手,但是如果字段不够,需要新增字段,会改动表结构。

纵表:扩展性更高,如果要增加一个字段,不需要改变表结构,但是一些关联查询会更加麻烦,也不便于维护与后续人员接手。

平常开发,尽量能用横表就不要用纵表,维护成本比较高昂,而且一些关联查询也很麻烦。

2、纵表转换为横表

(1)第一步,我们先把这些字段名以及相应字段的值从纵表中取出来


select r.original_record_id,r.did,r.device_sn,r.Mac_address,r.record_time, r.updated_time updated_time,
(case r.field_code when 'accumulated_cooking_time' then r.record_value else '' end ) accumulated_cooking_time,
(case r.field_code when 'data_version' then r.record_value else '' end) data_version,
(case r.field_code when 'loop_num' then r.record_value else '' end) loop_num,
(case r.field_code when 'status' then r.record_value else '' end) status
from ats_item_record r 
where item_code = 'GoNGMO_AGING'

结果:

 通过 case 语句,成功把字段从纵表中取出,但是此时仍算不上一个横表,我们这里的original_record_id 是记录同一行数据的唯一ID,我们这里可以通过这个字段把上面这四行合成一行记录。

注意:这里需要取出每一个字段,都要case一下,有多少个字段,就需要多少次case语句。因为一个case语句,遇到符合条件的when语句之后,后面的会不再执行。

(2)分组,合并相同行,生成横表


select * from (
	select r.original_record_id,
    max(r.did) did,
    max(r.device_sn) device_sn,
    max(r.mac_address) mac_address,
    max(r.record_time) record_time,
	max(r.updated_time) updated_time,
	max((case r.field_code when 'accumulated_cooking_time' then r.record_value else '' end )) accumulated_cooking_time,
	max((case r.field_code when 'data_version' then r.record_value else '' end)) data_version,
	max((case r.field_code when 'loop_num' then r.record_value else '' end)) loop_num,
	max((case r.field_code when 'status' then r.record_value else '' end)) status
	from ats_item_record r 
	where item_code = 'GONGMO_AGING'
	group by r.original_record_id
) m order by m.updated_time desc;

 查询的结果:

注意:这里采用group by 分组的时候,需要给字段加上max函数。用group by 分组的时候,一般搭配聚合函数使用,常见的聚合函数:

  • AVG() 求平均数
  • COUNT() 求列的总数
  • MAX() 求最大值
  • MIN() 求最小值
  • SUM() 求和

大家注意一下,我把纵表同一条记录的公共字段 r.original_record_id 放到了group by里面,这个字段在纵表中同一条记录相同、唯一,且永远不会改变(相当于以前横表的主键ID),然后把其他字段放到 max 中(因为其他字段要么是相同的,要么是取最大的就可以,要么是只有一个纵表记录有数值其他记录为空,所以这三种情况都可以直接用max),四条记录取最大的更新时间作为同一条记录的更新时间,在逻辑上也是合适的。然后我们把纵表字段 field_code 和 record_value 做了 max() 操作,因为同一条记录里面他们都是唯一存在的,不会发生同一条数据有两个相同的 field_code 记录,所以这样做 max() 也是没有任何问题的。

优化点:

最后这个SQL是可以优化一下的,我们可以把模板字段(r.original_record_id,r.did,r.device_sn,r.mac_address,r.record_time 等),从专门存放模板字段表中全部取出来(同一个逻辑纵表的字段全部取出),然后再代码里面拼接好我们的 max() 部分,作为参数拼接进去执行,这样可以做到通用,每次如果新增加模板字段,我们不需要更改这个SQL语句了(中国移动他们存放手机的参数数据就是这么干的)。

优化后的业务层(组装 SQL 模板的代码),代码如下:


@Override
public PageInfo<AtsAgingitemRecordVo> getAgingItemList(AtsItemRecordQo qo) {
    //1、获取工模老化字段模板
    LambdaQueryWrapper<AtsItemFieldPo> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.eq(AtsItemFieldPo::getItemCode, AtsItemCodeConstant.GONGMO_AGING.getCode());
    List<AtsItemFieldPo> fieldPoList = atsItemFieldDao.selectList(queryWrapper);
    //2、组装查询条件
    List<String> tplList = Lists.newArrayList(), conditionList = Lists.newArrayList(), validList = Lists.newArrayList();
    if (!CollectionUtils.isEmpty(fieldPoList)) {
        //3、组装动态max查询字段
        for (AtsItemFieldPo itemFieldPo : fieldPoList) {
            tplList.add("max((case r.field_code when '" + itemFieldPo.getFieldCode() + "' then r.record_value else '' end )) " + itemFieldPo.getFieldCode());
            validList.add(itemFieldPo.getFieldCode());
        }
        qo.setTplList(tplList);
        //4、组装动态where查询条件
        if (StringUtils.isNotBlank(qo.getDid())) {
            conditionList.add("AND did like CONCAT('%'," + qo.getDid() + ",'%')");
        }
        if (validList.contains("batch_code") && StringUtils.isNotBlank(qo.getBatchCode())) {
            conditionList.add("AND batch_code like CONCAT('%'," + qo.getBatchCode() + ",'%')");
        }
        qo.setConditionList(conditionList);
    }
    qo.setItemCode(AtsItemCodeConstant.GONGMO_AGING.getCode());
    //4、获取老化自动化测试项记录
    PageHelper.startPage(qo.getPageNo(), qo.getPageSize());
    List<Map<String, Object>> dataList = atsItemRecordDao.selectItemRecordListByCondition(qo);
    PageInfo pageInfo = new PageInfo(dataList);
    //5、组装返回结果
    List<AtsAgingItemRecordVo> recordVoList = null;
    if (!CollectionUtils.isEmpty(dataList)) {
        recordVoList = JSONUtils.copy(dataList, AtsAgingItemRecordVo.class);
    }
    pageInfo.setList(recordVoList);
    return pageInfo;
}

优化后的Dao层,代码如下:


public interface AtsItemRecordDao extends BaseMapper<AtsItemRecordPo> {
 
    List<Map<String, Object>> selectItemRecordListByCondition(AtsItemRecordQo qo);
}

优化后的SQL语句,代码如下:


<select id="selectItemRecordListByCondition" resultType="java.util.HashMap"
        parameterType="com.galanz.iot.ops.restapi.model.qo.AtsItemRecordQo">
    SELECT * FROM (
        SELECT r.original_record_id id,
        max(r.did) did,
        max(r.device_sn) device_sn,
        max(r.updated_time) updated_time,
        max(r.record_time) record_time,
        <if test="tplList != null and tplList.size() > 0">
            <foreach collection="tplList" item="tpl" index="index" separator=",">
                ${tpl}
            </foreach>
        </if>
        FROM ats_item_record r
        WHERE item_code = #{itemCode}
        GROUP BY r.original_record_id
    ) m
    <where>
        <if test="conditionList != null and conditionList.size() > 0">
            <foreach collection="conditionList" item="condition" index="index">
                ${condition}
            </foreach>
        </if>
    </where>
    ORDER BY m.updated_time DESC
</select>

模板字段表结构(ats_item_field 表),如下所示:

字段名 类型 长度 注释
id bigint 20 主键ID
field_code varchar 32 字段编码
field_name varchar 32 字段名称
remark varchar 512 备注
created_by bigint 20 创建人ID
created_time datetime 0 创建时间
updated_by bigint 20 更新人ID
updated_time datetime 0 更新时间

记录表结构(ats_item_record 表),如下所示:

字段名 类型 长度 注释
id bigint 20 主键ID
did varchar 64 设备唯一ID
device_sn varchar 32 设备sn
mac_address varchar 32 设备Mac地址
field_code varchar 32 字段编码
original_record_id varchar 64 原始记录ID
record_value varchar 32 记录值
created_by bigint 20 创建人ID
created_time datetime 0 创建时间
updated_by bigint 20 更新人ID
updated_time datetime 0 更新时间

注:original_record_id 是纵转横表后,每条记录的唯一ID,可以看做我们普通横表的主键ID一样的东西

到此 Mysql 纵表转换为横表介绍完成。

总结

到此这篇关于mysql纵表转换为横表的文章就介绍到这了,更多相关Mysql纵表转换为横表内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Mysql纵表转换为横表的方法及优化教程

本文链接: https://lsjlt.com/news/131849.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Mysql纵表转换为横表的方法及优化教程
    1、纵表与横表 纵表:表中字段与字段的值采用key—value形式,即表中定义两个字段,其中一个字段里存放的是字段名称,另一个字段中存放的是这个字段名称代表的字段的值。 例如,下面这...
    99+
    2024-04-02
  • MySQL横纵表相互转化操作实现方法
    本文实例讲述了MySQL横纵表相互转化操作实现方法。分享给大家供大家参考,具体如下: 先创建一个成绩表(纵表) create table user_score ( name varchar(20),...
    99+
    2022-05-24
    MySQL 横纵表 转化
  • MySQL大表优化的方法教程
    本篇内容介绍了“MySQL大表优化的方法教程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!单表优化除非单表...
    99+
    2024-04-02
  • oracle表优化方法教程
    这篇文章主要讲解了“oracle表优化方法教程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“oracle表优化方法教程”吧!1、建立实验表create ta...
    99+
    2024-04-02
  • oracle普通表转化为分区表的方法
    上一篇文章中我们了解了oracle数据与文本导入导出源码示例的相关内容,接下来我们看看,oracle中如何将普通表转化为分区表的方法。 oracle官方建议当表的大小大于2GB的时候就使用分区表进行管理,分...
    99+
    2024-04-02
  • MySQL 临时表的原理以及优化方法
    目录1 临时表2 union临时表优化3 group by临时表优化1 临时表 sort buffer、内存临时表和join buffer,这三个数据结构都是用来存放语句执行过程中的中间数据,以辅助SQL语句的...
    99+
    2022-08-22
    MySQL 临时表优化 MySQL 临时表
  • Python中将字典转换为列表的方法
    说明:列表不可以转换为字典 ①转换后的列表为无序列表 a = {'a' : 1, 'b': 2, 'c' : 3} #字典中的key转换为列表 key_value = list(a.keys()) p...
    99+
    2022-06-04
    转换为 中将 字典
  • Python | 将字符串转换为列表的7种方法
    在本文中,我们将尝试将给定的字符串转换为列表,其中根据用户的选择,遇到空格或任何其他特殊字符。为此,我们在string中使用split()方法。 例如: 输入: “Geeks for Geeks”...
    99+
    2023-10-11
    python
  • python把元组转换为列表的方法是什么
    要将元组转换为列表,可以使用内置函数list()。以下是使用list()函数将元组转换为列表的示例:pythontuple1 = (...
    99+
    2023-10-21
    python
  • 快速转换numpy数组为列表的方法分享
    快速转换numpy数组为列表的方法分享 在数据处理和分析中,经常会使用到numpy库来进行快速、高效的数组操作。然而,有时候我们需要将numpy数组转换为列表进行进一步的处理或者与其他类型的数据进行交互。下面我将分享一些快速转换...
    99+
    2024-01-19
    列表 转换 numpy数组
  • Python二维列表创建、转换及访问的方法
    本文小编为大家详细介绍“Python二维列表创建、转换及访问的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python二维列表创建、转换及访问的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、概念二...
    99+
    2023-06-30
  • numpy数组转换为列表:优化数据结构的实用技术
    数据分析领域常用的Python库Numpy是一个基于数组的库,它提供速度快、高效和便捷的数学操作。Numpy中的数组是其最基础的数据结构,它是一个容易处理和操作的高维数列。在数据的预处理过程中,我们常常需要把Numpy中的数组转...
    99+
    2024-01-19
    数据结构优化 列表转换 numpy数组
  • Python实现csv文件(点表和线表)转换为shapefile文件的方法
    Python实现csv文件(点表和线表)转换为shapefile文件 说明 点表使用的geometry坐标是wkbPoint(几何点坐标) 线表使用的geometr...
    99+
    2024-04-02
  • mysql回表查询优化的方法是什么
    MySQL回表查询是指在使用索引扫描后,仍需要通过主键再次访问表数据的操作。这种情况通常发生在需要查询的列不在索引中,或者是使用覆盖...
    99+
    2024-04-09
    mysql
  • mysql多表关联优化的方法是什么
    优化多表关联的方法有以下几种: 使用索引:在关联字段上建立索引可以加快查询速度。确保每个表的关联字段都有索引,并且尽量使用覆盖索引...
    99+
    2024-03-06
    mysql
  • MySQL索引管理优化的方法教程
    这篇文章主要讲解了“MySQL索引管理优化的方法教程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL索引管理优化的方法教程”吧! ...
    99+
    2024-04-02
  • MySQL流转工具Maxwell的代码改造和优化方法教程
    本篇内容介绍了“MySQL流转工具Maxwell的代码改造和优化方法教程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能...
    99+
    2024-04-02
  • MySQL表结构优化管理的方法是什么
    MySQL表结构优化管理的方法包括以下几个方面: 正确选择数据类型:选择适当的数据类型可以减小存储空间的占用,并提高查询和索引的...
    99+
    2023-10-24
    MySQL
  • Java 列表转换为数组的3种详细方法介绍
    1.介绍 List 接口提供了一种存储有序集合的方法。它是 Collection 的子接口。它是一个有序的对象集合,其中可以存储重复值。由于 List 保留了插入顺序,因此它允许元素的位置访问和插入。...
    99+
    2023-09-22
    java jvm 开发语言
  • 在 PHP 中将数组转换为不重复列表的方法
    php 中将数组转换为不重复列表的方法有多种:array_unique() 函数:将数组中的值与键关联,选择键对应的第一个值为不重复元素。array_flip() 和 array_key...
    99+
    2024-04-28
    列表 php 数组
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作