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

1. 行转列

例子:找出取经组中每人打怪的总数,并一行显示
原始数据:

+-----------+-------+
| user_name | kills |
+-----------+-------+
| 孙悟空 | 10 |
| 孙悟空 | 2 |
| 孙悟空 | 12 |
| 孙悟空 | 22 |
| 猪八戒 | 20 |
| 猪八戒 | 17 |
| 猪八戒 | 35 |
| 沙僧 | 3 |
| 沙僧 | 9 |
| 沙僧 | 5 |
+-----------+-------+

想要的数据:

+-----------+-----------+--------+
| 孙悟空 | 猪八戒 | 沙僧 |
+-----------+-----------+--------+
| 46 | 72 | 17 |
+-----------+-----------+--------+

sql如下:
select sum(case when user_name='孙悟空' then kills end) '孙悟空',
   sum(case when user_name='猪八戒' then kills end) '猪八戒',
   sum(case when user_name='沙僧' then kills end) '沙僧'
from user1_kills;

2. 使用子查询避免重复数据

例子:找出取经组中有打怪记录的人
取经组user1

+----+-----------+-----------------------------+---------------------------------+
| id | user_name | comment | mobile |
+----+-----------+-----------------------------+---------------------------------+
| 1 | 唐僧 | 旃檀功德佛 | 138245623,021-382349 |
| 2 | 孙悟空 | 此人在悟空的朋友圈 | 159384292,022-483432,+86-392432 |
| 3 | 猪八戒 | 净坛使者 | 183208243,055-8234234 |
| 4 | 沙僧 | 金身罗汉 | 293842295,098-2383429 |
| 5 | NULL | 白龙马 | 993267899 |
+----+-----------+-----------------------------+---------------------------------+

打怪记录user1_kills

+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 1 | 孙悟空 | 2013-01-10 00:00:00 | 10 |
| 2 | 孙悟空 | 2013-02-01 00:00:00 | 2 |
| 3 | 孙悟空 | 2013-02-05 00:00:00 | 12 |
| 4 | 孙悟空 | 2013-02-12 00:00:00 | 22 |
| 5 | 猪八戒 | 2013-01-11 00:00:00 | 20 |
| 6 | 猪八戒 | 2013-02-07 00:00:00 | 17 |
| 7 | 猪八戒 | 2013-02-08 00:00:00 | 35 |
| 8 | 沙僧 | 2013-01-10 00:00:00 | 3 |
| 9 | 沙僧 | 2013-01-22 00:00:00 | 9 |
| 10 | 沙僧 | 2013-02-11 00:00:00 | 5 |
+----+-----------+---------------------+-------+

join写法:
select a.id, a.user_name from user1 a join user1_kills b on (a.user_name = b.user_name);

+----+-----------+
| id | user_name |
+----+-----------+
| 2 | 孙悟空 |
| 2 | 孙悟空 |
| 2 | 孙悟空 |
| 2 | 孙悟空 |
| 3 | 猪八戒 |
| 3 | 猪八戒 |
| 3 | 猪八戒 |
| 4 | 沙僧 |
| 4 | 沙僧 |
| 4 | 沙僧 |
+----+-----------+

可以看到通过join写法,会存在一些重复记录,此时需要在sql语句中加distinct,即select distinct a.id...

in写法:
select user_name from user1 where user_name in (select user_name from user1_kills2);

+-----------+
| user_name |
+-----------+
| 孙悟空 |
| 猪八戒 |
| 沙僧 |
+-----------+

因此不同的写法如果存在结果集数量不一致的情况,可以看看是否有重复数据

3. 多列过滤

例子:查询出取经组中每人打怪最多的日期
user1_kills表,取经路上杀的妖怪数量

+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 1 | 孙悟空 | 2013-01-10 00:00:00 | 10 |
| 2 | 孙悟空 | 2013-02-01 00:00:00 | 2 |
| 3 | 孙悟空 | 2013-02-05 00:00:00 | 12 |
| 4 | 孙悟空 | 2013-02-12 00:00:00 | 22 |
| 5 | 猪八戒 | 2013-01-11 00:00:00 | 20 |
| 6 | 猪八戒 | 2013-02-07 00:00:00 | 17 |
| 7 | 猪八戒 | 2013-02-08 00:00:00 | 35 |
| 8 | 沙僧 | 2013-01-10 00:00:00 | 3 |
| 9 | 沙僧 | 2013-01-22 00:00:00 | 9 |
| 10 | 沙僧 | 2013-02-11 00:00:00 | 5 |
+----+-----------+---------------------+-------+

在我的另一篇文章https://www.cnblogs.com/ddzj01/p/11346954.html中提到了两种sql写法
聚合子查询写法:
select * from user1_kills a where a.kills = (select max(b.kills) from user1_kills b where b.user_name = a.user_name);
join写法:
select a.* from user1_kills a join user1_kills b on (a.user_name = b.user_name) group by a.id, a.user_name, a.timestr, a.kills having a.kills = max(b.kills);

这里介绍另一种写法:
select * from user1_kills a where (a.user_name, a.kills) in (select b.user_name, max(b.kills) from user1_kills b group by b.user_name);

+----+-----------+---------------------+-------+
| id | user_name | timestr | kills |
+----+-----------+---------------------+-------+
| 4 | 孙悟空 | 2013-02-12 00:00:00 | 22 |
| 7 | 猪八戒 | 2013-02-08 00:00:00 | 35 |
| 9 | 沙僧 | 2013-01-22 00:00:00 | 9 |
+----+-----------+---------------------+-------+

4. 计算个人所得税

salary表

+----+-----------+-----------------+-------+
| id | user_name | comment | money |
+----+-----------+-----------------+-------+
| 1 | 唐僧 | 旃檀功德佛 | 35000 |
| 2 | 孙悟空 | 斗战胜佛 | 28000 |
| 3 | 猪八戒 | 净坛使者 | 15000 |
| 4 | 沙僧 | 金身罗汉 | 8000 |
+----+-----------+-----------------+-------+

tax表

+----+-------+---------+------+
| id | low | high | rate |
+----+-------+---------+------+
| 1 | 0 | 1500 | 0.03 |
| 2 | 1500 | 4500 | 0.10 |
| 3 | 4500 | 9000 | 0.20 |
| 4 | 9000 | 35000 | 0.25 |
| 5 | 35000 | 55000 | 0.30 |
| 6 | 55000 | 1000000 | 0.35 |
+----+-------+---------+------+

例子:算出取经组中每人的个人所得税

计算个人所得税,属于经典题目了,下面看看用sql如何实现
首先,直接对两表进行笛卡尔连接,为了节约篇幅,只取唐僧的数据查看
select * from salary a join tax b order by user_name, low;

+----+-----------+-----------------+-------+----+-------+---------+------+
| id | user_name | comment | money | id | low | high | rate |
+----+-----------+-----------------+-------+----+-------+---------+------+
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 1 | 0 | 1500 | 0.03 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 2 | 1500 | 4500 | 0.10 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 3 | 4500 | 9000 | 0.20 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 4 | 9000 | 35000 | 0.25 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 5 | 35000 | 55000 | 0.30 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 6 | 55000 | 1000000 | 0.35 |
+----+-----------+-----------------+-------+----+-------+---------+------+

可以看到最后两条数据不需要,因为它的low都大于等于money,所以可以加上连接条件a.money > b.low,排除不需要的行
select * from salary a join tax b on (a.money > b.low) order by user_name, low;

+----+-----------+-----------------+-------+----+------+-------+------+
| id | user_name | comment | money | id | low | high | rate |
+----+-----------+-----------------+-------+----+------+-------+------+
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 1 | 0 | 1500 | 0.03 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 2 | 1500 | 4500 | 0.10 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 3 | 4500 | 9000 | 0.20 |
| 1 | 唐僧 | 旃檀功德佛 | 35000 | 4 | 9000 | 35000 | 0.25 |
+----+-----------+-----------------+-------+----+------+-------+------+

接下来只需要计算每一行的税费即可,计算的标准则为least(money, high) - low,因此sql如下
select a.user_name, sum((least(a.money, b.high) - b.low) * b.rate) total from salary a join tax b on (a.money > b.low) group by a.user_name;

+-----------+---------+
| user_name | total |
+-----------+---------+
| 唐僧 | 7745.00 |
| 孙悟空 | 5995.00 |
| 沙僧 | 1045.00 |
| 猪八戒 | 2745.00 |
+-----------+---------+

不管是开发人员还是dba,都应该熟练掌握sql技巧,本文例子取自于慕课网《sql开发技巧》。如果文章对你有帮助,不妨点个赞,支持下博主。

Mysql - 开发技巧(二)的更多相关文章

  1. SQL开发技巧(二)

    本系列文章旨在收集在开发过程中遇到的一些常用的SQL语句,然后整理归档,本系列文章基于SQLServer系列,且版本为SQLServer2005及以上-- 文章系列目录 SQL开发技巧(一) SQL开 ...

  2. SQL开发技巧(二) 【转】感觉他写的很好

    本文转自: http://www.cnblogs.com/marvin/p/DevelopSQLSkill_2.html 本系列文章旨在收集在开发过程中遇到的一些常用的SQL语句,然后整理归档,本系列 ...

  3. MYSQL 开发技巧

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

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

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

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

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

  6. MySQL开发技巧

    MySQL基础表和数据 如何进行行列转换 行转列 场景:报表统计(sum()).汇总显示表数据:select * from score; 希望达到的效果 cross join SQL如下: selec ...

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

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

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

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

  9. CSS开发技巧(二):表格合并边框后的单元格宽度计算

    前言: 分离边框模型和合并边框模型是表格的两种模型,它通过以下属性确定: border-collapse:separate(默认值) | collapse | inherit 当采用分离边框模型时,表 ...

随机推荐

  1. Vue ---- 表单指令 条件指令 循环指令 分隔符 过滤器 计算属性 监听属性

    目录 案例讲解: 一. 表单指令 1.重点: 补充 2.单选框 3.单一复选框 4.多复选框 二 . 条件指令 v-if/v-show ... v-clock 三 . 循环指令 string arra ...

  2. django基础之day08,分页器从无到有,动态思路解析全过程

    *********分页器从无到有的全过程,动态思路解析如下:******** 1.通过book_queryset = models.Book.objects.all()[start_num:end_n ...

  3. HTTP 错误 500.19 - Internal Server Error解决办法详解

    最近在服务器端部署程序发现这个问题,HTTP 错误 500.19 - Internal Server Error,程序在本地跑是没有问题的.但是部署完,浏览程序就出现这个问题,今天这篇文章就是记录一下 ...

  4. [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]

    我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...

  5. Dc:7 Vulnhub Walkthrough

    靶机下载地址: https://www.vulnhub.com/entry/dc-7,356/ 主机扫描: http://10.10.202.161/ Google搜索下: SSH 登录 以上分析得出 ...

  6. Android 再次打开APP进入按Home键退出时的界面(thisTaskRoot)

    问题 Android 设置页面的启动模式为 singletask 之后,当按Home 退出时,再重新打开应用,还会进入首启动页.就会造成一些应用需要重新登录,当前页数据丢失等问题 解决 去除启动页的 ...

  7. Git很麻烦?只要掌握这几个命令,轻松将代码提交远程仓库

    在上一章节,跟大家介绍了拉取代码的操作,简单暴力.这一章节要介绍的是如何将现有的项目,直接提交到仓库. 现在,如果大家有一个项目要提交到GitHub仓库,安装上一张的方法,需要先在GitHub上建一个 ...

  8. 第2章:C++泛型机制的基石:数据类型表——《C++泛型:STL原理和应用》读书笔记整理

    第二章:C++泛型机制的基石--数据类型表 2.1 类模板的公有数据类型成员 2.1.1 类的数据类型成员   C++类中不仅可以定义数据成员和函数成员,而且还可以定义数据类型成员.在泛型设计中,类的 ...

  9. 新学期教育教学小学家长会PPT模板推荐

    模版来源:http://ppt.dede58.com/jiaoxuekejian/26569.html

  10. HTML入门(html基本文本标签+快捷键讲解以及基本html组成解释)

    id 标签 功能  1  <hr /> 水平分割线  2 <br /> 强制让文本换行  3 <p>段落</p> 段落标签(自带换行效果)  4 < ...