周总找我问个报表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. Cloudflare 重定向配置

    最近把之前的一个网站域名换成另一个域名,想要添加一下重定向,避免流量流失(虽然本来就没流量).然后在 Cloudflare 配置时尝试多次都失败了,遇到各种 Your connection is no ...

  2. 微服务探索之路06篇k8s配置文件Yaml部署Redis使用Helm部署MongoDB和kafka

    1 安装Redis 1.1创建配置文件redis.conf 切换到自己的目录下如本文是放在/home/ubuntu下 cd /home/ubuntu vim redis.conf bind 0.0.0 ...

  3. 快速掌握Vue3:速成Vue3前端开发看这篇就够啦

    一.Vue基本概念 1.1-Vue3的优点 Vue3支持Vue2额大多数特性. 更好的支持TypeScript. 打包大小减少41%. 初次渲染快55%,更新渲染快133%. 内存减少54%. 使用p ...

  4. nflsoj 5926 素数环

    题目非常简单,只需要判断相邻两个数的和是不是素数,素数的判断参考数论 不过要注意的一点是题目说的是一个环,所以首尾两个数的和也要是素数 我在输出的时候加上了 is_prime(path[n-1]+1) ...

  5. 状压DP-学习笔记

    状压DP 状压 \(DP\) 是一种基于二进制数的 \(DP\). T1 题目大意 将一个整数 \(N\) 分解成若干个小整数的乘积,满足: 分解出的整数必须来自集合 \(S\). 分解出的整数必须互 ...

  6. 联通光猫获取超级管理员密码,联通宽带逻辑ID 获取

    首先使用普通账户登录然后访问这个链接 http://192.168.1.1/backpresettings.conf 保存backpresettings.conf 打开文件就可以看到 cuadmin ...

  7. Codeforces 1462F The Treasure of The Segments

    题意 给\(n(1\leq n\leq 2*10^5)\)个线段$[l_i,r_i] (1≤l_i≤r_i≤10^9) $,问最少删除几个线段,使得剩下线段中,有至少一个线段与所有线段相交. 分析 对 ...

  8. crm--纯后端部署

    博客地址:https://www.cnblogs.com/zylyehuo/ 技术栈:supervisor + nginx + uwsgi + django + virtualenv + mariad ...

  9. maven缺失ojdbc6解决方法(手动安装ojdbc6)

    maven缺失ojdbc6解决方法(手动安装ojdbc6) 1. 首先下载ojdbc6jar包 jar下载地址一(需登录) jar下载地址二(直接下载) 2. 进入到jar包所在文件夹,执行cmd命令 ...

  10. Vite+ts+springboot项目集成2

    项目集成 集成element-plus 官网地址: 安装图标库 pnpm install element-plus @element-plus/icons-vue 入口文件main.ts全局安装ele ...