周总找我问个报表SQL实现逻辑的案例,废话不说给他看看。

原SQL:

SELECT d.tname   姓名,
d.spname 岗位,
d.sum_cnt 报单单量,
d.min_cnt 放款单量,
d.date 月份
FROM (SELECT *
FROM (SELECT a.zts_name tname,
a.sp_name spname,
CONVERT(ifnull(a.order_cnt, '0'), SIGNED) sum_cnt,
CONVERT(ifnull(b.order_cnt, '0'), SIGNED) min_cnt,
a.gmt_create DATE
FROM
(
SELECT
t.zts_name, t.sp_name, count( t.order_no ) AS order_cnt, DATE_FORMAT ( t.gmt_create, '%Y-%m' ) gmt_create
FROM
(
SELECT
zts.`name` AS zts_name,
ztr.`name` AS sp_name,
rto.order_no,
rto.gmt_create AS gmt_create
FROM
AAAA rto
INNER JOIN BBBB rts ON rto.id = rts.order_id
INNER JOIN CCCC zts ON rts.principal_id = zts.id
INNER JOIN DDDD ztj ON zts.id = ztj.staff_id
INNER JOIN EEEE ztr ON ztj.role_id = ztr.id
WHERE
rts.role = '7'
AND ztr.`description` = '客户经理' ) t
GROUP BY
t.zts_name
) A
LEFT JOIN (
SELECT
t.zts_name,
t.sp_name,
count( t.order_no ) AS order_cnt,
DATE_FORMAT( t.gmt_create, '%Y-%m' ) gmt_create
FROM
(
SELECT
zts.`name` AS zts_name,
ztr.`name` AS sp_name,
rto.order_no,
rto.gmt_create AS gmt_create
FROM
AAAA rto
INNER JOIN BBBB rts ON rto.id = rts.order_id
INNER JOIN CCCC zts ON rts.principal_id = zts.id
INNER JOIN DDDD ztj ON zts.id = ztj.staff_id
INNER JOIN EEEE ztr ON ztj.role_id = ztr.id
WHERE
rto.state IN ( 4010, 4030 )
AND rts.role = '7'
AND ztr.`description` = '客户经理' ) t
GROUP BY
t.zts_name
) b
ON A.zts_name = b.zts_name
AND A.gmt_create = b.gmt_create) c
ORDER BY c.date ASC,
CONVERT(c.sum_cnt, signed) DESC) d;

精简后的结果集:

 周总的意思很简单,就是以 月份 来分组,求出 报单数量 在不同月份中的中位数就行。

这道题读者不需要过多关注原来的SQL是如何写的,只需要把重点放在如何取 报单数量 的中位数即可。

中位数:在一个数列中,如果按照大小顺序排列,中位数就是位于中间的那个数。

这道SQL的解题思路其实很简单:

  1、使用 DENSE_RANK 开窗函数对 月份分组 ,然后对 报单数量排序,注意:不能使用 ROW_NUMBER() 和 RANK() 进行排序,这两个函数一个会给连续的序号,另外一个会跳号。

       2、然后对 DENSE_RANK 开窗函数 的排序结果进行 max 开窗取每个月的最大序号。

       3、最后使用 每个月的最大序号除以2 就可以得出不同月份的中位数。

最终SQL代码:

SELECT *
FROM ( /* FLOOR(j.最大的编号 / 2) 中位数编号 最后使用 每个月的最大序号除以2 就可以得出不同月份的中位数。 */ SELECT j.姓名,
j.岗位,
j.报单单量,
j.放款单量,
j.月份,
j.编号,
FLOOR(j.最大的编号 / 2) 中位数编号
FROM ( /* MAX(x.rn) OVER (PARTITION BY x.月份 ) 最大的编号 然后对 DENSE_RANK 开窗函数 的排序结果进行 max 开窗取每个月的最大序号 */ SELECT x.姓名,
x.岗位,
x.报单单量,
x.放款单量,
x.月份,
x.rn 编号,
MAX(x.rn) OVER (PARTITION BY x.月份 ) 最大的编号
FROM ( /* DENSE_RANK() OVER (PARTITION BY d.date ORDER BY d.sum_cnt) rn 对月份分组 ,然后对报单数量排序 */ SELECT
d.tname 姓名,
d.spname 岗位,
d.sum_cnt 报单单量,
d.min_cnt 放款单量,
d.date 月份,
DENSE_RANK() OVER (PARTITION BY d.date ORDER BY d.sum_cnt) rn
FROM ( /* 以下SQL为原始SQL */
SELECT *
FROM (
SELECT a.zts_name tname,
a.sp_name spname,
CONVERT(ifnull(a.order_cnt, '0'), SIGNED) sum_cnt,
CONVERT(ifnull(b.order_cnt, '0'), SIGNED) min_cnt,
a.gmt_create DATE
FROM
(
SELECT
t.zts_name, t.sp_name, count( t.order_no ) AS order_cnt, DATE_FORMAT ( t.gmt_create, '%Y-%m' ) gmt_create
FROM
(
SELECT
zts.`name` AS zts_name,
ztr.`name` AS sp_name,
rto.order_no,
rto.gmt_create AS gmt_create
FROM
AAAA rto
INNER JOIN BBBB rts ON rto.id = rts.order_id
INNER JOIN CCCC zts ON rts.principal_id = zts.id
INNER JOIN DDDD ztj ON zts.id = ztj.staff_id
INNER JOIN EEEE ztr ON ztj.role_id = ztr.id
WHERE
rts.role = '7'
AND ztr.`description` = '客户经理' ) t
GROUP BY
t.zts_name
) A
LEFT JOIN (
SELECT
t.zts_name,
t.sp_name,
count( t.order_no ) AS order_cnt,
DATE_FORMAT( t.gmt_create, '%Y-%m' ) gmt_create
FROM
(
SELECT
zts.`name` AS zts_name,
ztr.`name` AS sp_name,
rto.order_no,
rto.gmt_create AS gmt_create
FROM
AAAA rto
INNER JOIN BBBB rts ON rto.id = rts.order_id
INNER JOIN CCCC zts ON rts.principal_id = zts.id
INNER JOIN DDDD ztj ON zts.id = ztj.staff_id
INNER JOIN EEEE ztr ON ztj.role_id = ztr.id
WHERE
rto.state IN ( 4010, 4030 )
AND rts.role = '7'
AND ztr.`description` = '客户经理' ) t
GROUP BY
t.zts_name
) b
ON A.zts_name = b.zts_name
AND A.gmt_create = b.gmt_create) c
ORDER BY c.date ASC,
CONVERT(c.sum_cnt, signed) DESC) d) x) j) g
WHERE g.编号 = g.中位数编号;

最后可以看到该SQL已经改写成功,可以列出不同月份 达到中位数的销售姓名的单量。

其实这条SQL不算很难,只是最近在戒烟,注意力集中不了思考了好一会才实现,哎戒烟真的是太痛苦了。

SQL改写案例4(开窗函数取中位数案例)的更多相关文章

  1. SQL ServerOVER 子句,over开窗函数,SQL SERVER 开窗函数

    https://technet.microsoft.com/zh-cn/library/ms189461(v=sql.105).aspx http://www.cnblogs.com/85538649 ...

  2. sql server中的开窗函数over、视图、事物

    一.开窗函数over的作用有两个: 1.排序order by,row_number,翻页 2.划区partition by,结合聚合函数针对某部分数据进行汇总 翻页的sql server 语句: an ...

  3. 利用over开窗函数取第一条记录

    SQL> set linesize 200 SQL> select * from (select a.* ,row_number() over( order by empno) rn  f ...

  4. SQL之开窗函数详解--可代替聚合函数使用

    在没学习开窗函数之前,我们都知道,用了分组之后,查询字段就只能是分组字段和聚合的字段,这带来了极大的不方便,有时我们查询时需要分组,又需要查询不分组的字段,每次都要又到子查询,这样显得sql语句复杂难 ...

  5. SQL SERVER开窗函数

    作为一名开发人员来讲,我感觉在职场白混了好多年,可能是自己真的没有进取的精神吧,看了<程序员的SQL金典>这本电子书,真的让我学到了不少知识,真心喜欢这本电子书,书中讲解的内容比较好懂,也 ...

  6. (011)每日SQL学习:SQL开窗函数

    开窗函数:在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成.为了解决这些问题,在 2003 年 ISO SQL 标准加入了开窗函数,开窗函数的 ...

  7. sqlserver开窗函数

    从 http://jimshu.blog.51cto.com/3171847/1376637/ 转 开窗函数是在 ISO 标准中定义的.SQL Server 提供排名开窗函数和聚合开窗函数. 在开窗函 ...

  8. mysql为何不支持开窗函数?

    引用 在开窗函数出现之前存在着非常多用 SQL 语句非常难解决的问题,非常多都要通过复杂的相关子查询或者存储过程来完毕.为了解决这些问题,在2003年ISO SQL标准增加了开窗函数,开窗函数的使用使 ...

  9. SQL Server标量函数改写内联表值函数优化案例

    问题SQL: SELECT TOP 1001 ha.HuntApplicationID , ha.PartyNumber , mht.Name AS MasterHuntTypeName , htly ...

  10. sql server ,OVER(PARTITION BY)函数用法,开窗函数,over子句,over开窗函数

    https://technet.microsoft.com/zh-cn/library/ms189461(v=sql.105).aspx https://social.msdn.microsoft.c ...

随机推荐

  1. 重温C#中的值类型和引用类型

    在C#中,数据类型分为值类型和引用类型两种. 引用类型变量存储的是数据的引用,数据存储在数据堆中,而值类型变量直接存储数据.对于引用类型,两个变量可以引用同一个对象.因此,对一个变量的操作可能会影响另 ...

  2. jQuery事件冒泡和默行为

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 让nodejs开启服务更简单--express篇

    上一篇文章说到,nodejs获取客户端请求需要我们自己去处理请求参数.请求方式等,而在express框架内部集成了很多好用的方法,我们不需要从0开始编写各种处理逻辑,这样可以极大提高我们的开发效率~ ...

  4. Nginx快速入门:简介、安装、配置

    Nginx概述 与 Apache 软件类似,Nginx ("engine x")是一个开源的.支持高性能.高并发的web服务和代理服务软件.它是由俄罗斯人 Igor Sysoev ...

  5. el-date-picker 在表单中宽度(width)问题

    在使用element-plus的日期选择组件 el-date-picker的时候,发现form表单内的日期选择框并不能跟el-input 一样把宽度撑满.而是要小一圈. 这样在排版中显得不太整齐,但是 ...

  6. [ABC138F] Coincidence

    2023-02-03 题目 题目传送门 翻译 翻译 难度&重要性(1~10):6 题目来源 AtCoder 题目算法 数位dp 解题思路 \(1.\) 当 \(2x\leq y\),有\(y- ...

  7. 《Linux基础》04. 用户管理 · 用户组 · 相关文件 · 权限管理

    @ 目录 1:用户管理指令 1.1:添加用户 1.2:修改用户密码 1.3:用户切换与注销 1.4:删除用户 1.5:查询用户信息 1.6:查看当前登录用户 1.7:查看有哪些用户 2:用户组指令 2 ...

  8. CodeForces 1187E Tree Painting

    题意:给定一棵\(n\)个点的树 初始全是白点 要求你做\(n\)步操作,每一次选定一个与一个黑点相隔一条边的白点,将它染成黑点,然后获得该白点被染色前所在的白色联通块大小的权值. 第一次操作可以任意 ...

  9. CFS-GA 相关性特征选择与遗传算法 特征选择/特征提取

    CFS-GA特征选择/特征提取 CFS 对于一个样本空间,构造一个二维矩阵A代表此样本空间,A中每行代表一条数据,每列代表一个特征 样本中的数据分为数个特征,其中\(A_i\)表示第\(i\)个特征, ...

  10. Springboot简单功能示例-5 使用JWT进行授权认证

    springboot-sample 介绍 springboot简单示例 跳转到发行版 查看发行版说明 软件架构(当前发行版使用) springboot hutool-all 非常好的常用java工具库 ...