MySQL基础表和数据

如何进行行列转换

行转列

场景:报表统计(sum())、汇总显示
表数据:
select * from score;

希望达到的效果

cross join

SQL如下:

select a.student_name '学生名', a.score '语文', b.score '数学', c.score '英语' from
(select student_name, score from score where course_name='语文') a
cross join
(select student_name, score from score where course_name='数学') b
cross join
(select student_name, score from score where course_name='英语') c
where a.student_name = b.student_name and b.student_name = c.student_name;

使用case

但是使用case的时候达到的效果不好,如下:

SQL如下:

select student_name '学生名',
case when course_name = '语文' then score end '语文',
case when course_name = '数学' then score end '数学',
case when course_name = '英语' then score end '英语'
from score;

解决方案:在case的基础上使用分组,并使用sum()函数,SQL如下:

select student_name,
sum(case
when course_name = '语文' then score
else 0
end) '语文',
sum(case
when course_name = '数学' then score
else 0
end) '数学',
sum(case
when course_name = '英语' then score
else 0
end) '英语'
from score
group by student_name;

列转行

场景:属性拆分
表数据:
select * from interest;

希望达到的效果

SQL如下:

-- 需要使用序列表处理列转行的数据
create table tb_sequence(
id int primary key auto_increment
); -- 取决于逗号分割的数据量,这里兴趣爱好最多的就四个,那就暂时插入4条数据
insert into tb_sequence values(), (), (), (); select student_name '学生名', replace(substr(substring_index(interesting, ',', a.id), char_length(substring_index(interesting, ',', a.id - 1)) + 1), ',', '') '兴趣爱好'
from tb_sequence a
cross join
(select student_name, concat(interesting, ',') interesting, length(interesting) - length(replace(interesting, ',', '')) + 1 size from interest) b
on a.id <= b.size;

场景:多列转行
表数据:
select * from student_dress;

希望达到的效果:

union all

SQL如下:

select student_name, 'cap' as '类别', cap '名称' from student_dress
union all
select student_name, 'clothing' as '类别', clothing '名称' from student_dress
union all
select student_name, 'pants' as '类别', pants '名称' from student_dress
union all
select student_name, 'shoe' as '类别', shoe '名称' from student_dress order by student_name;

使用case

希望达到的效果:

SQL如下:

select student_name '学生名', coalesce(
case when b.id = 1 then cap end,
case when b.id = 2 then clothing end,
case when b.id = 3 then pants end,
case when b.id = 4 then shoe end
) '名称' from student_dress a cross join tb_sequence b where b.id <= 4 order by student_name;

希望添加类别上去:

SQL如下:

select student_name '学生名',
case
when b.id = 1 then 'cap'
when b.id = 2 then 'clothing'
when b.id = 3 then 'pants'
when b.id = 4 then 'shoe' end '类别',
coalesce(
case
when b.id = 1 then cap
when b.id = 2 then clothing
when b.id = 3 then pants
when b.id = 4 then shoe end
) '名称' from student_dress a cross join tb_sequence b where b.id <= 4 order by student_name;

如何生成唯一序列号

场景:数据库主键、业务序列号如发票号、车票号、订单号等。。。
生成序列号的方法:
MySQL:AUTO_INCREMENT
SQLServer:INDENTIDYTY/SEQUENCE
Oracle:SEQUENCE
PgSQL: SEQUENCE
优先选择系统提供的序列号生成方式
在特殊情况下可以使用SQL方式生成序列号

如何删除重复数据

产生数据重复的原因:
人为原因,如复录入数据,重复提交等。。。
系统原因,由于系统升级或者设计的原因使原来可以重复的数据变为不重复了
如何查询数据是否重复:
利用group by和having从句处理
如何处理重复的数据:
删除重复的数据,对于相同数据保留ID最大的

-- 创建测试删除重复数据表
CREATE TABLE `test_repeat` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- 执行至少两次,这里执行两次即可
insert into test_repeat(name) values('Jef'); -- 查询出的内容为执行的上处插入的条数
select * from test_repeat where name = 'Jef'; -- 1、先把需要删除的数据查出来:
select a.id, a.name from test_repeat a join (
select name, count(*) cnt, max(id) maxId
from test_repeat
group by name having cnt > 1) b on a.name = b.name where a.id < b.maxId; -- 拷贝上处语句,查询改为删除即可
delete a from test_repeat a join (
select name, count(*) cnt, max(id) maxId
from test_repeat
group by name having cnt > 1) b on a.name = b.name where a.id < b.maxId; -- 再次执行1处的SQL(所有情况),发现没有需要删除的数据了,或者执行查询全部的SQL(数据量少的情况下使用)
select * from test_repeat;

如何在子查询中匹配两个值

常见的子查询使用场景
使用子查询可以避免由于子查询中的数据产生的重复
例子:
查询在超市购买过商品的学生名
select student_name '学生名' from student where student_id in(select student_id from student_shopping);


实现了去重
但是如果不用子查询,使用内连接
select student_name '学生名' from student s join student_shopping sp on s.student_id = sp.student_id;
这样购买了几件商品就会显示几次

可以使用distinct去重
select distinct student_name '学生名' from student where student_id in(select student_id from student_shopping);
使用子查询更符合语意,更好理解
查询出每一个学生购物种类最多的日期,并列出学生名,购物日期,购物种类
SQL如下:
select a.student_name '学生名', b.buy_date '购买日期', b.maxNum '购买种类' from student a join (select student_id, max(num) maxNum, buy_date from student_shopping group by student_id) b on a.student_id = b.student_id;

多列过滤的使用场景:
MySQL中独有的多列过滤方式
SQL如下,效果跟上图一样:
select a.student_name '学生名', b.buy_date '购买日期', b.num '购买种类' from student a join student_shopping b on a.student_id = 
b.student_id where (b.student_id, b.num) in (select student_id, max(num) from student_shopping group by student_id);

如何解决同一属性的多值过滤

什么是同一属性的多值过滤
查询出含有Java技能并且技能等级>3的学生名、技能和技能等级
SQL如下:
select a.student_name '学生名', b.skill_name '技能名称', b.skill_level '技能等级' from student a join student_skill b on a.student_id = b.student_id where b.skill_name = 'Java' and b.skill_level > 3;

MySQL开发技巧的更多相关文章

  1. Mysql - 开发技巧(二)

    本文中的涉及到的表在https://github.com/YangBaohust/my_sql中 本文衔接Mysql - 巧用join来优化sql(https://www.cnblogs.com/dd ...

  2. MYSQL 开发技巧

    主要涉及:JOIN .JOIN 更新.GROUP BY HAVING 数据查重/去重 1 INNER JOIN.LEFT JOIN.RIGHT JOIN.FULL JOIN(MySQL 不支持).CR ...

  3. MYSQL开发技巧之行转列和列转行

    行转列--两种方法第一种方法:行转列我们通常是使用交叉连接和子查询的方式做到,比如下面的例子,查询每个name的对应id的和mysql> select * from user; +----+-- ...

  4. Mysql开发技巧之删除重复数据

    Mysql利用联表查询和分组来删除重复数据 //删除表中重复的id,保留最大的id mysql> select * from user; +----+------+ | id | name | ...

  5. 慕课网--mysql开发技巧一 学习笔记

    现在存在下面的两张表,表的结构如下所示 师徒四人表结构:id,user_name,over数据:id user_name over1 唐僧 旃檀功德佛2 猪八戒 净坛使者3 孙悟空 斗战胜佛4 沙僧 ...

  6. MySQL开发技巧 第二禅(子查询中匹配两个值、解决同属性多值过滤的问题、计算累进税的问题)

    https://blog.csdn.net/xiesq5112/article/details/52154169

  7. MySQL开发规范与使用技巧总结

    命名规范 1.库名.表名.字段名必须使用小写字母,并采用下划线分割. a)MySQL有配置参数lower_case_table_names,不可动态更改,Linux系统默认为 0,即库表名以实际情况存 ...

  8. DelphiXE2 DataSnap开发技巧收集

    DelphiXE2 DataSnap开发技巧收集 作者:  2012-08-07 09:12:52     分类:Delphi     标签: 作为DelphiXE2 DataSnap开发的私家锦囊, ...

  9. NodeJS+Express+MySQL开发小记(2):服务器部署

    http://borninsummer.com/2015/06/17/notes-on-developing-nodejs-webapp/ NodeJS+Express+MySQL开发小记(1)里讲过 ...

随机推荐

  1. bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...

  2. bzoj千题计划112:bzoj1022: [SHOI2008]小约翰的游戏John

    http://www.lydsy.com/JudgeOnline/problem.php?id=1022 http://www.cnblogs.com/TheRoadToTheGold/p/67448 ...

  3. 51 nod 1058 N的阶乘的长度

    1058 N的阶乘的长度 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 输入N求N的阶乘的10进制表示的长度.例如6! = 720,长度为3.   In ...

  4. SpringBoot 线程池配置 实现AsyncConfigurer接口方法

      目的是:  通过实现AsyncConfigurer自定义线程池,包含异常处理  实现AsyncConfigurer接口对异常线程池更加细粒度的控制 *a) 创建线程自己的线程池  b) 对void ...

  5. bzoj 5085: 最大——结论题qwq

    Description 给你一个n×m的矩形,要你找一个子矩形,价值为左上角左下角右上角右下角这四个数的最小值,要你最大化矩形 的价值. Input 第一行两个数n,m,接下来n行每行m个数,用来描述 ...

  6. 【BZOJ】3786: 星系探索

    [题意]给定一棵带点权树,三种操作: 1.询问点x到根的路径和 2.子树x内的点权加定值y 3.将点x的父亲更换为y,保证仍是树. [算法]平衡树(fhq-treap) [题解] 将树的dfs序作为序 ...

  7. 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛:Frequent Subsets Problem (状态压缩)

    题目链接 题目翻译: 给出一个数n,和一个浮点数a,数n代表全集U = {1,2,...,n},然后给出 M个U的子集,如果一个集合B(是U的子集),M个集合中有至少M*a个集合包含B, 则B这个集合 ...

  8. js模拟自动点击事件

    1.直接上代码很直观 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  9. 【译】第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

  10. 引发类型为“System.OutOfMemoryException”的异常

    在运维工作中,经常能接到客户的反馈这个:引发类型为“System.OutOfMemoryException”的异常.客户反馈物理内存都还有富余,怎么报内存不足的错误呢! 什么时候会引发System.O ...