行列转换(一)• MySQL版

news2024/11/17 4:38:47

请添加图片描述

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流

本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle

请添加图片描述

行列转换 • Mysql版

  • 1.准备操作
  • 2.行转列
    • 1.1为何进行行转列?
    • 1.2 行转列有两个意思:1.表内的行转列 2.跨表的行转列
  • 3.行转列的思路:行变少,列变多
    • 3.1 如何进行行转列:增加字段,进行聚合(行变少)
  • 4.行转列的实操
    • 4.1 通用的行转列(Mysql和Oracle都能用)
      • 4.1.1想在结果中加入学生名字
        • 4.1.1.1加入名字的方法1:

1.准备操作

  • 先建一个表
create table table_grade(
id int,
user_name varchar(20),
course varchar(10),
score decimal(5,2)
);
  • 练习 三种插入
insert into table_grade(id,user_name,course,score) values (1,'张龙','语文','78'),(2,'张龙','数学','95'),(3,'张龙','英语','81');
insert into table_grade values(4,'赵虎','语文','97'),(5,'赵虎','数学','78'),(6,'赵虎','英语','91');
insert into table_grade set id = 7,user_name = '王五',course = '语文',score = '81';
insert into table_grade set id = 8,user_name = '王五',course = '数学',score = '55';
insert into table_grade set id = 9,user_name = '王五',course = '英语',score = '75';
insert into table_grade values(10,'马六','语文','87'),(11,'马六','数学','65'),(12,'马六','英语','75');
  • 修改列类型
alter table table_grade modify score decimal;  -- decimal默认10位整数

2.行转列

1.1为何进行行转列?

  • 现实中用到的一些数据是明细数据/流水账
    用户名 商品 购买时间
    A 手机 4.20
    A U盘 4.21
    B …
    B …

    • 如上,展示的就是明细数据,每个用户有多条商品的购买记录,这种明细数据称为【多用户集】,往往我们想换一种展示的方式,因为每个用户有多个数据,想把这种多用户的数据变成单用户数据,即【单用户集】,如下
      用户名 最近一次购买商品 最近两次购买商品 A U盘 手机
      B … …
      • 显然,单用户集展示的信息更多一点,对于上面的多用户集,如果一个用户拥有太多条信息,就会看着很乱,所以需要变成单用户集
      • 单用户集有个问题,就是列需要不断的增加,存储方面的开销会大一点,因为需要给它分配很多列的空间
      • 明细数据经常以如上所示的纵表的方式,所以又称为【纵表】,因为它的数据是以堆叠的方式显示的(一个用户有多条记录),即stack方式显示;单用户集是以列的方式显示的,又称为【横表】,所以将多用户集变成单用户集的方式又称为【行转列】或【unstack】过程
      • 行转列后的单用户集数据,更适合做数据分析,如上面的单用户集,可以很直观的看到最近一次或最近两次的购买数据,而如果是看上面的多用户集,还得根据时间去比较,才可以看到一些隐藏信息
      • 列转行,就是将单用户集再转回多用户集

1.2 行转列有两个意思:1.表内的行转列 2.跨表的行转列

  • 跨表就是假设除了购买商品的流水,还有其他的一些流水,也是与用户ID一起记录的,比如用户的积分表,也可以对上面的单用户集进行关联,使单用户集的列增多。经常将跨表的行转列,列变多的过程,称为拉宽的过程
  • 称上面那种购物明细表为【事实表】,多个事实表通过键关联,就会拉宽字段(维度+指标)
update table_grade set id = 4 where user_name = '马六'

alter table table_grade add oid varchar(10)

alter table table_grade modify oid varchar(50)

update table_grade set oid = uuid();  -- 设置一个代理键

alter table table_grade rename column id to user_id -- 修改某列名字

alter table table_grade modify oid varchar(50) first  -- 修改某列位置

show columns from table_grade;   -- 查看表各列

show keys from table_grade;   -- 查看索引

3.行转列的思路:行变少,列变多

3.1 如何进行行转列:增加字段,进行聚合(行变少)

  • 通过聚合将多用户变成单用户,使用哪一个聚合函数与数据有关

  • 使用max()则选取最大的一条

  • 现在的表如下所示
    张龙 语文 78
    张龙 数学 95
    张龙 英语 81
  • 我们想显示成:
    语文 数学 英语
    张龙 78 95 81
  • 这样的话,张龙语文只能有一个成绩,若有多个成绩
    • ** 思路1:用列表把多个成绩放在一起 **
      语文 数学 英语
      张龙 78,88 95 81
    • ** 思路2:取一个最近的考试成绩(这就需要在表中加一个时间列)**
    • ** 思路3:如果两次成绩重复了,比如都是100,就可以用max或min**
      语文 数学 英语
      张龙 100 95 81
      • 如果用sum的话,统计结果就变成了200
        语文 数学 英语
        张龙 200 95 81
        - 增加一个时间限制
alter table table_grade add column exam_date date after score;
  • 设置随机时间
update table_grade set exam_date = date_format(from_unixtime(  -- from_unixtime() 将时间戳转换为日期,date_format()设置一下日期格式
unix_timestamp('2023-01-01')    -- 将日期转为一个时间戳,此处是用1月1号加随机的天数(由于天数是1月1到4月28,所以最终的结果不会超过4月28)
+ floor( rand() *               -- rand() 随机数[0,1),floor() 向下取整
		(unix_timestamp('2023-04-28') - unix_timestamp('2023-01-01') + 1) -- 4月28减去1月1号的天数,因为rand的范围是[0,1),所以后面+1是为了保证可以取得4月28
	) 
	),'%Y-%m-%d');

4.行转列的实操

  • 前提: 假设张龙各科只考了一次,对此进行行转列

    • 为了可以看出差异性,删除王五的英语,马六的语文
    delete from table_grade where user_name = '王五' and course = '英语';
    delete from table_grade where user_name = '马六' and course = '语文';
    

4.1 通用的行转列(Mysql和Oracle都能用)

select user_id '学生ID', 
			 max(case when course = '语文' then score else null end) '语文',  -- 因为只有一个成绩,max min 没区别; else null 可以省略,默认其他情况就是null
			 max(case when course = '数学' then score end) '数学',
			 max(case when course = '英语' then score end) '英语'
from table_grade
group by user_id  -- 用了聚合函数,那就用group by 去显示

4.1.1想在结果中加入学生名字

  • 如果直接在group by 中加入user_name,是可以的执行的,这样group by的粒度会变细,细粒度的字段可以带粗粒度的字段(此处指select,因为select中只有user_id这一个字段)
  • 如果把user_name加在select子句中,这样在mysql是可以执行的(我这里的mysql8出错了,可能8修改了这个),在orale中是不能执行的。即使mysql中可以执行,那意思就是按照user_id分组,然后带出一个比较细的划分user_id+user_name,而一个user_id可能对应多个user_name,那应该取哪一个呢?mysql会自动取分组中的第一个user_name
  • 不要在group by中加入名字,因为可能会重名

4.1.1.1加入名字的方法1:

select user_id '学生ID',
			 (select max(user_name) from table_grade where user_id = t.user_id) user_name, -- 使用相关子查询(关联子查询)
			 max(case when course = '语文' then score end) '语文',
			 max(case when course = '数学' then score end) '数学',
			 max(case when course = '英语' then score end) '英语'
from table_grade t
group by user_id;
  • 相关子查询中的聚合函数与外面的聚合函数是由区别的,外面的聚合函数是同时按照所有的分组去求最大值的,相关子查询中的聚合函数是外层传入一个值,在内层进行一次查询。
  • 平时的左关联右关联可能会产生笛卡尔积,但是关联子查询是不会产生笛卡尔积的,因为它每次外查询传入一个值,所以永远都是外对内是一对多,不会造成笛卡尔积
  • 上面的相关子查询中加max()是为了防止出错,因为表中同一个ID对应多个名字,如果不加max()的话,就会报错:Subquery returns more than 1 row,即子查询返回了多行。所以此处需要加一个函数进行处理,至于决定加哪一个函数,根据需求决定,这后面讲
  • 加入名字还有一种写法就是select … from in ——> 用in也最好是in(1,2) 这种小的组合,如果在in里面嵌套select查询,这种不太好理解,层数太多了

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/689690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue前端和nodejs后端使用socket.io无法通信问题解决

(128条消息) 使用 socket.io 跨域问题的解决(整理了四种方法,总有成功的!) Access to XMLHttpRequest at ‘http://localhost:4000/socket.io_socket io()出现跨域问题_it1790的博客-CSDN博客 socket.io的版本是4.6.2

【Java】Java核心 73:XML (中)

文章目录 5 XML的组成:字符区(了解)**6** **DTD约束(能够看懂即可)****1** **什么是DTD****2** **DTD约束的实现和语法规则(看懂dtd约束,书写符合规范的xml文件)** 5 XML的组成:字符区(了解) 当大量的转义字符出现在x…

MATLAB随机打乱矩阵(按行或列)

1、重新排列矩阵各行 a [1 2;3 4;5 6;7 8]; rowrank randperm(size(a, 1)); % size获得a的行数,randperm打乱各行的顺序 a1 a(rowrank,:) % 按照rowrank重新排列各行,注意rowrank的位置2、重新排列矩阵各列 b [1 3 5 7;2 4 6 8 ]; r…

【AntDB数据库】AntDB数据库整体架构

整体架构 AntDB包括计算节点(Coordinator)、数据节点(DB)、全局事务管理器(GTM)和管理节点四种组件,其中GTM和DB为有状态的组件,需要考虑高可用,架构如下图: 计算节点(Coordinator):提供SQL解…

ffmpeg dec中AVCodecHWConfigInternal在那里使用

在做ffmpeg decode插件的时候,发现需要增加一个AVCodecHWConfigInternal数组, //就是这个数组 static const AVCodecHWConfigInternal *efcodec_hw_configs[] {&(const AVCodecHWConfigInternal) {.public {.pix_fmt AV_PIX_FMT_EFCCODEC,.me…

Jupyter notebook运行环境创建

进入到jupyter notebook,没找到自己之前创建的环境xzc_pytorch 进入到Anaconda prompt,输入如下命令 (xzc_pytorch) C:\Users\xzc> conda install ipykernel安装完后,重启jupyter notebook发现还是没有 ,此时选择手动创建,在base环境下执…

【Nginx】第四章 Nginx配置实例-反向代理

4.1 反向代理实例一 实现效果:使用nginx反向代理,访问 www.123.com 直接跳转到localhost:8080 4.1.1 实验准备工作 启动一个 tomcat,浏览器地址栏输入 localhost:8080,出现如下界面 在liunx系统安装tomcat,使用默认…

【运维部署】亚马逊云服务器安装后通过Xhell远程登录提示“所选的用户密钥未在远程主机上注册。请再试一次”

这里写自定义目录标题 背景解决方案第一步 确认配置第二步 确认权限方案C 背景 最新亚马逊云服务准备扩容,新建了一台Ubuntu服务器,密钥对使用原来服务器上的密钥对,创建后直接迁移到了新的服务器上。 通过 less .ssh/authorized_keys 可以查…

【Rust】1、实战:语法和数据结构、生命周期-所有权-借用、自制 CPU、内存

文章目录 一、概述1.1 安全性1.1.1 垂悬指针1.1.2 数据竞争1.1.3 迭代器失效 1.2 性能1.3 vscode 設置 二、基础语法2.1 循环2.2 引用2.3 生命周期2.4 泛型2.5 实战grep项目2.6 数组2.6.1 数组和切片2.6.2 动态数组2.6.3 初始化 2.7 包含第三方库2.8 命令行参数2.9 读文件2.9.1…

Python零基础入门(六)——超详细的字符串与正则表达式

系列文章目录 个人简介:机电专业在读研究生,CSDN内容合伙人,博主个人首页 Python入门专栏:《Python入门》欢迎阅读,一起进步!🌟🌟🌟 码字不易,如果觉得文章不…

基于java的汽车服务管理系统(Car Service Management System)

设计一款基于java的管理和跟踪对车辆所做服务的系统。我们的系统允许服务技术人员跟踪客户、他们的车辆以及对这些车辆所做的服务。 需要项目的朋友私信我!!!!!! Car Service Management System 基本的使用…

【OpenCV • c++】颜色数据结构与颜色空间转换

🚀 个人简介:CSDN「博客新星」TOP 10 , C/C 领域新星创作者💟 作 者:锡兰_CC ❣️📝 专 栏:【OpenCV • c】计算机视觉🌈 若有帮助,还请关注➕点赞➕收藏&#xff…

chatgpt赋能python:Python:一个值得花钱学习的编程语言

Python:一个值得花钱学习的编程语言 近年来,Python成为了一款备受欢迎的编程语言,尤其在数据科学、人工智能等领域表现出色。许多人开始进入Python编程领域,而且Python培训课程也爆发式增长。但是,一些人对于Python的…

react中基于腾讯云cos上传图片组件

react中基于腾讯云cos上传图片组件 效果示例图上传图片组件imageUploadcomponents/imageUpload/index.jsxcomponents/imageUpload/upload.scss 使用组件 效果示例图 上传图片组件imageUpload npm install cos-js-sdk-v5 -S components/imageUpload/index.jsx import ".…

Mac 打开/关闭 iCloud 后导致桌面文件夹、文档删除,恢复步骤!

不小心打开/关闭了 iCloud 后,导致桌面内容全部丢失,再次打开同步,发现还是确实很多内容,如何找回最初的文件副本。 当 iCloud 关闭时,会将任何未上传到 iCloud 云盘的文稿内容转移打包放到当前 Mac 电脑的个人文件夹…

ChatGPT批量生成文章软件:助力创作高效快捷文章

随着人工智能技术的不断发展,ChatGPT批量生成文章软件已经成为了一种强大的创作工具。它能够通过自然语言处理和机器学习算法,快速生成高质量的文章,为创作者提供了高效快捷的创作体验。本文将从随机8-20个方面对ChatGPT批量生成文章软件进行…

【从零开始学习JAVA | 第二十一篇】常见API介绍 System

目录 前言: System: System类中静态方法: 总结: 前言: system 是一个很底层的 API,是一个工具类,提供了一些与系统相关的方法。他在我们写项目的时候提供了一些非常实用的方法,本…

基于Filebeat+Kafka+ELK实现Nginx日志收集并采用Elastalert2实现钉钉告警

目录 基于FilebeatKafkaELK实现Nginx日志收集1.规划好项目架构图2.部署前端web集群3.部署ES集群集群介绍环境准备集群搭建分片和副本 4.部署kafka集群环境准备静态IP配置重启网络服务域名解析设置安装时间同步服务关闭防火墙和selinux kafka集群依赖于zookeeperkafaka和zookeep…

8 系统定时器(Systick)

目录 系统定时器(Systick) SysTick定时器特性介绍 SysTick定时器的功能 SysTick定时器寄存器介绍 Systick定时器的使用 系统定时器(Systick) SysTick定时器特性介绍 计数宽度: 24bit来存储数据,2^24…

HOT21-搜索二维矩阵II

leetcode原题链接: 搜索二维矩阵II 题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1: 输入:matrix [[…