mysql实现开窗函数

http://blog.itpub.net/29989552/viewspace-2123077/

学习过oracle的应该知道,oracle中的分析函数功能十分强大,包括mssql、postgresql等数据库都支持开窗函数。然而mysql至今都没有提供这样的功能,今天就来探讨下用mysql实现一些开窗功能需求。
实验数据:表sale
| month  | user_id | amount |
+--------+---------+--------+
| 201601 | 1       |    500 |
| 201601 | 2       |    300 |
| 201601 | 3       |    100 |
| 201602 | 1       |   1000 |
| 201602 | 2       |    800 |
| 201603 | 2       |   1000 |
| 201603 | 3       |    500 |
| 201604 | 1       |   1000 |

需求一:求每个月的销售额及累计销售额(二月份额累计销售额是一月销售额加二月销售额)
开窗函数实现:
select month,sum(amount),sum(sum(amount)) over (ORDER BY month) from sale GROUP BY month ORDER BY month
 month  | sum  | sum  
--------+------+------
 201601 |  900 |  900
 201602 | 1800 | 2700
 201603 | 1500 | 4200
 201604 | 1000 | 5200
轻松完成需求

mysql实现:
select
a.month,a.amount,sum(b.amount)
from (select month,sum(amount) amount from sale GROUP BY month) a CROSS JOIN (select month,sum(amount) amount from sale GROUP BY month) b
where a.month>=b.month GROUP BY a.month,a.amount

+--------+--------+---------------+
| month  | amount | sum(b.amount) |
+--------+--------+---------------+
| 201601 |    900 |           900 |
| 201602 |   1800 |          2700 |
| 201603 |   1500 |          4200 |
| 201604 |   1000 |          5200 |
可以看出相比较于开窗函数,mysql实现起来很麻烦,先用子查询将每个月的销售汇总,再将两个子查询做笛卡尔积,性能肯定比开窗差很多,如果子查询结果集很多,做笛卡尔积是个灾难!

需求二:每个月销售冠军及销售额
开窗函数实现:
select month,user_id,amount
from
(select
month,user_id,amount,
row_number() over (PARTITION by month ORDER BY amount desc) rn
from sale) a where a.rn=1

month  | user_id | amount
--------+---------+--------
 201601 | 1       |    500
 201603 | 2       |   1000
 201602 | 1       |   1000
 201604 | 1       |   1000

mysql实现:
方法一:
select a.*
  from (select t1.*,
               (select count(*) + 1
                  from sale
                 where month = t1.month
                   and amount > t1.amount) as group_id
          from sale t1) a
 where a.group_id = 1;

+--------+---------+--------+----------+
| month  | user_id | amount | group_id |
+--------+---------+--------+----------+
| 201601 | 1       |    500 |        1 |
| 201603 | 2       |   1000 |        1 |
| 201602 | 1       |   1000 |        1 |
| 201604 | 1       |   1000 |        1 |
+--------+---------+--------+----------+
这个样的方式同样是用笛卡尔积得出和开窗rank一样的结果列出来

方法二:
select month,user_id,max(amount) from sale GROUP BY month

| month  | user_id | max(amount) |
+--------+---------+-------------+
| 201601 | 1       |         500 |
| 201602 | 1       |        1000 |
| 201603 | 2       |        1000 |
| 201604 | 1       |        1000 |

mysql实现起来简单,但是注意,这个语句是不严谨的,因为user_id没有跟在group by后面,这是其他数据库所不允许。在mysql5.6中默认的sql_mode只有NO_ENGINE_SUBSTITUTIO,这样的语法可以使用,如果sql_mode有ONLY_FULL_GROUP_BY的限制,则无法使用这样的语法。mysql5.7的sql_mode就默认含有ONLY_FULL_GROUP_BY。

f

mysql实现开窗函数的更多相关文章

  1. mysql实现开窗函数、Mysql实现分析函数

    关键字:mysql实现开窗函数.Mysql实现分析函数.利用变量实现窗口函数 注意,变量是从左到右顺序执行的 --测试数据 CREATE TABLE `tem` ( `id` ) NOT NULL A ...

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

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

  3. mysql 实现类似开窗函数的功能

    mysql8 已经支持开窗函数 https://dev.mysql.com/doc/refman/8.0/en/window-functions.html ———————————————— sql s ...

  4. Mysql 开窗函数实战

    Mysql 开窗函数实战 Mysql 开窗函数在Mysql8.0+ 中可以得以使用,实在且好用. row number() over rank() over dense rank() ntile() ...

  5. Oracle开窗函数 over()(转)

    copy文链接:http://blog.csdn.net/yjjm1990/article/details/7524167#,http://www.2cto.com/database/201402/2 ...

  6. (MariaDB)开窗函数用法

    本文目录: 1.1 窗口和开窗函数简介 1.2 OVER()语法和执行位置 1.3 row_number()对分区排名 1.4 rank()和dense_rank() 1.5 percent_rank ...

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

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

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

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

  9. Mysql - 存储过程/自定义函数

    在数据库操作中, 尤其是碰到一些复杂一些的系统, 不可避免的, 会用到函数/自定义函数, 或者存储过程. 实际项目中, 自定义函数和存储过程是越少越好, 因为这个东西多了, 也是一个非常难以维护的地方 ...

随机推荐

  1. 软件工程课开学测试——根据已有的CSS模板资源,搭建整个系统

    日期:2019.2.28 博客期:038 星期四 今天的测试得到了9.5分,将将及格的程度吧!本次程序完成的很不成功! <%@ page language="java" co ...

  2. nl命令

    nl (Number of Lines) 将指定的文件添加行号标注后写到标准输出.如果不指定文件或指定文件为"-" ,程序将从标准输入读取数据. 选项: -b, --body-nu ...

  3. Kafka集群搭建 (2.11-0.9.0.1)

    之前写过kafka_2.9.2-0.8.2.2版本的安装,kafka在新的0.9版本以上改动比较大,配置和api都有很大更新,并且broker对应的partition支持多线程生产和消费,所以性能比之 ...

  4. KaliLinuxNetHunter教程下载相关资源

    KaliLinuxNetHunter教程下载相关资源 当用户将刷机工具准备完后,则需要下载ROM包.ROM是ROM image(只读内存镜像)的简称,常用于手机定制系统.一般手机刷机的过程,就是将只读 ...

  5. Python3虚拟环境--venv

    Python3.3以上的版本通过venv模块原生支持虚拟环境,可以代替之前的virtualenv. 该venv模块提供了创建轻量级“虚拟环境”,提供与系统Python的隔离支持.每一个虚拟环境都有其自 ...

  6. [C#] 動的にアセンブリをロードする

    アプリケーション ドメインにおいて起動時に読み込まれない別のアセンブリ (.dll や .exe) を読み込む場合.System.Reflection.Assemby クラスの Load メソッドを使 ...

  7. 【Codeforces】【图论】【数量】【哈密顿路径】Fake bullions (CodeForces - 804F)

    题意 有n个黑帮(gang),每个黑帮有siz[i]个人,黑帮与黑帮之间有有向边,并形成了一个竞赛完全图(即去除方向后正好为一个无向完全图).在很多年前,有一些人参与了一次大型抢劫,参与抢劫的人都获得 ...

  8. python3.7 打包成exe程序(只需两行命令)

    根据博客作者louniuous的python3.7 打包成exe的一种方法 pyinstaller一文改编简化 环境:pycharm2018.1+win7+python3.7 工具:pyinstall ...

  9. 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D

    目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...

  10. 查找已连接过的wifi密码

    无意之间看到能破解已连接过的wifi密码的诀窍,赶紧存储下来. 1. 首先打开终端 2. 在没有网路的情况下输入: netsh wlan show profiles 结果如下(自己的): 这些‘用户配 ...