当前位置: 首页 > news >正文

SQL 层面行转列

背景:

如果对一些评论、点赞、收藏等互动数据,使用了按照 type 分类存储,num 也是对应的。

这样如果创建一个帖子,那么就会出现 3 行数据(type 不同,num 不同,对应评论点赞和收藏),那如果我返回给前端,只想返回一行。
即 3 行数据转化为 3 列属性(评论、点赞、收藏)。

本文就是一个项目中的一个举例,不再单独举例子。

这里只关注了 sql编写,到 mapper 中怎么写,关于中间接口的定义,就不再赘述。

前端需要的字段都在,AlbumListVo中,不代表所有的都在一个数据表中,所以需要联查才可以。

@Data
@Schema(description = "专辑信息")
public class AlbumInfoVo {@NotEmpty(message = "专辑标题不能为空")@Length(min = 2, message = "专辑标题的长度必须大于2")@Schema(description = "标题", required=true)private String albumTitle;@Positive(message = "三级分类不能为空")@Schema(description = "三级分类id", required=true)private Long category3Id;@NotEmpty(message = "专辑简介不能为空")@Schema(description = "专辑简介", required=true)private String albumIntro;@NotEmpty(message = "专辑封面不能为空")@Schema(description = "专辑封面图", required=true)private String coverUrl;@Schema(description = "预计更新多少集")private Integer estimatedTrackCount;@Schema(description = "专辑简介,富文本")private String albumRichIntro;@NotEmpty(message = "付费类型不能为空")@Schema(description = "付费类型: 0101-免费、0102-vip免费、0103-付费", required=true)private String payType;@Schema(description = "价格类型: 0201-单集 0202-整专辑")private String priceType;@Schema(description = "原价")@JsonSerialize(using = Decimal2Serializer.class)private BigDecimal price;@Schema(description = "0.1-9.9  不打折 -1")@JsonSerialize(using = Decimal2Serializer.class)private BigDecimal discount = new BigDecimal(-1);@Schema(description = "0.1-9.9 不打折 -1")@JsonSerialize(using = Decimal2Serializer.class)private BigDecimal vipDiscount = new BigDecimal(-1);@Schema(description = "免费试听集数")private Integer tracksForFree;@Schema(description = "每集免费试听秒数")private Integer secondsForFree;@Schema(description = "购买须知,富文本")private String buyNotes;@Schema(description = "专辑卖点,富文本")private String sellingPoint;@Schema(description = "是否公开:0-否 1-是")private String isOpen;//递归校验//@Valid//@NotEmpty(message = "属性值集合不能为空")@Schema(description = "属性值集合")private List<AlbumAttributeValueVo> albumAttributeValueVoList;@NotEmptyPaid(message = "价格类型不能为空")public String getPayTypeAndPriceType() {return this.getPayType() + "_" + this.getPriceType();}@NotEmptyPaid(message = "价格不能为空")public String getPayTypeAndPrice() {return this.getPayType() + "_" + this.getPrice();}
}

在 sql 里面查关联表。

不同维度,你是4 行,但是我想要 1593 的4列属性,最后封装在一个Vo实体类中

selectalbum_info.id as albumId,album_info.album_title,album_info.cover_url,album_info.include_track_count,album_info.is_finished,album_info.status,album_stat.stat_num,album_stat.stat_typefrom album_infoinner join album_stat
on album_stat.album_id=album_info.id
where album_info.user_id = 19;

对于同一个albumId应该所有的属性在一行中,所以我们对他们进行分组一下

但是分组是有要求的:

分组划分的这一列必须是表的主键,不是就爆炸

这里首先以单个表来演示:

selectalbum_info.id as albumId,album_info.album_titlefrom album_info
where album_info.user_id = 19
group by album_info.id;

如果不是主键列进行分组

selectalbum_info.id as albumId,album_info.album_titlefrom album_info
where album_info.user_id = 19
group by album_info.user_id;

按照分组的列查询,但是如果有的了后面任意

selectalbum_info.user_id
这加其他列也一样报错from album_info
where album_info.user_id = 19
group by album_info.user_id;

分组的规则:

mysql5.7 后有一种模式,sql规范的模式:sql_mode,其中涉及到分组

单表

        分组是主键,select 后面可以跟这个表中的任意列

        不是主键 select 只能跟上分组的列,以及其他列的聚合函数处理后的结果

多表

        即使是主键分组,依然需要聚合函数处理

        这个跟了主键,但是加了聚合函数是成功了

selectalbum_info.user_id,count(album_info.id)
from album_info
where album_info.user_id = 19
group by album_info.user_id;

那如果是多表呢?做聚合函数

这里是个多表,哪怕是主键,后面有其他表,依然得用聚合函数!

那怎么去映射呢 4 行变 4列

我们这里用到了一个 if 函数,最后还是套聚合函数!

selectalbum_info.id as albumId,album_info.album_title,album_info.cover_url,album_info.include_track_count,album_info.is_finished,album_info.status,count(if(album_stat.stat_type='0401', album_stat.stat_num, 0)) as playStatNumfrom album_infoinner join album_stat
on album_stat.album_id=album_info.id
where album_info.user_id = 19
group by album_info.id;

这里只是显现了一行,但是如果 4 行转化也是同样的

因为要做一个分页,我们再进行一个排序。

order by album_info.update_time desc

编码实现

转到 mapper.xml 中写 sql,对写的sql 进行一个简单的更改

这里没去校验 userId 是因为这个前面使用了 TingshuLogin,不登录肯定不行

AlbumInfoMapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.anran.tingshu.album.mapper.AlbumInfoMapper"><select id="findUserAlbumPage" resultType="com.anran.tingshu.vo.album.AlbumInfoVo">selectalbum_info.id as albumId,album_info.album_title,album_info.cover_url,album_info.include_track_count,album_info.is_finished,album_info.status,max(if(album_stat.stat_type='0401', album_stat.stat_num, 0)) as playStatNum,max(if(album_stat.stat_type='0402', album_stat.stat_num, 0)) as subscribeStatNum,max(if(album_stat.stat_type='0403', album_stat.stat_num, 0)) as buyStatNum,max(if(album_stat.stat_type='0404', album_stat.stat_num, 0)) as commentsStatNumfrom album_infoinner join album_staton album_stat.album_id=album_info.id<where><if test="vo.albumTitle != null and vo.albumTitle != ''">and album_info.album_title=#{vo.albumTitle}</if><if test="vo.status != null and vo.status != ''">and album_info.status=#{vo.status}</if>and album_info.user_id=#{vo.userId} and album_info.is_deleted=0</where>group by album_info.idorder by album_info.update_time desc</select>
</mapper>
  • 因为不需要自定义数据,在 sql 方面完成了封装,所以不需要 mybatis 封装 ,所以直接返回值就是resultType而不是resultMap


文章转载自:

http://Gb7bYCqe.npxcc.cn
http://ZBqxVntt.npxcc.cn
http://b6txNoNN.npxcc.cn
http://MCVOHGzd.npxcc.cn
http://FR9zK9Vu.npxcc.cn
http://d93WOFoV.npxcc.cn
http://q0P5XqfM.npxcc.cn
http://pE4Wrsl9.npxcc.cn
http://lA3GImmx.npxcc.cn
http://uwUe3eY7.npxcc.cn
http://ZaC8VZKC.npxcc.cn
http://S0JIAqGH.npxcc.cn
http://ZTOP6XgV.npxcc.cn
http://5obHcJVs.npxcc.cn
http://SAlutFq5.npxcc.cn
http://Bj6pbrZP.npxcc.cn
http://kddlxKi0.npxcc.cn
http://aIX9WCHk.npxcc.cn
http://AOHK13b1.npxcc.cn
http://b4k2ty6i.npxcc.cn
http://ljpYf3Jh.npxcc.cn
http://sdvQFCdL.npxcc.cn
http://ZYUVENxi.npxcc.cn
http://NIs4jZNj.npxcc.cn
http://CT051Uwe.npxcc.cn
http://WnvuQjF9.npxcc.cn
http://ZdKgyRT2.npxcc.cn
http://HekbZ3ac.npxcc.cn
http://u4nXGzxE.npxcc.cn
http://CadmRBLf.npxcc.cn
http://www.dtcms.com/a/373469.html

相关文章:

  • XR数字融合工作站赋能新能源汽车专业建设的创新路径
  • 大模型(LLM)安全保障机制(技术、标准、管理)
  • 【LeetCode】String相关算法练习
  • Redis基本数据类型
  • 深度学习(三):监督学习与无监督学习
  • crew AI笔记[5] - knowledge和memory特性详解
  • MyBatis多数据库支持:独立 XML 方案与单文件兼容方案的优劣势分析及选型建议
  • 安卓玩机工具----安卓“搞机工具箱”最新版 控制手机的玩机工具
  • 100、23种设计模式之适配器模式(9/23)
  • Docker网络模式解析
  • ARM处理器基础
  • TDengine 选择函数 First 用户手册
  • 9.8网编基础知识day1
  • 卷积神经网络(CNN):从图像识别原理到实战应用的深度解析
  • 【LeetCode - 每日1题】将整数转换为两个无零整数的和
  • 【超详细图文教程】2025年最新 Jmeter 详细安装教程及接口测试示例
  • MongoDB 常见错误解决方案:从连接失败到主从同步问题
  • Guava中常用的工具类
  • Entity Digital Sports 降低成本并快速扩展
  • 计算机毕业设计选题:基于Spark+Hadoop的健康饮食营养数据分析系统【源码+文档+调试】
  • Rust异步运行时最小实现 - extreme 分享
  • 内网穿透的应用-Navidrome与cpolar本地搭建跨网络访问的云音乐服务器
  • 金融量化指标--2Alpha 阿尔法
  • Qoder 完整使用指南
  • Coze源码分析-资源库-删除插件-后端源码-数据访问和基础设施层
  • GitHub OAuth 登录实现
  • 容器-资源隔离机制
  • WGAI项目前后端项目简介及首页监控
  • 前端通过后端给的webrtc的链接,在前端展示,并更新实时状态
  • 如何安装 Google 通用的驱动以便使用 ADB 和 Fastboot 调试(Bootloader)设备