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. Java_日期时间相关类

    目录 Date类(java.util.date) Calendar类(java.util.Calendar) SimpleDateFormat类(java.text.SimpleDateFormat) ...

  2. php的参数函数与可变参

    在php5.5及更早的版本中,使用func_num_args(), func_get_arg(), func_get_args()函数实现. <?php function myfunc(){ / ...

  3. jq-css、class、属性操作

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

  4. SQL Server中文排序混乱

    在sql语句中指定了含有中文的列进行排序,但排序结果看起来毫无规则,并不是按照拼音进行排序的检查了DB的Collation后,发现是SQL_Latin1_General_CP1_CI_AS解决方法: ...

  5. 剑指offer字符串列表

    字符串 面试题5:替换空格 面试题20:表示数值的字符串 面试题58:翻转字符串 面试题58(二):左旋转字符串

  6. windows环境jprofiler配置监控tomcat

    1.点击jprofiler/bin/jprofiler.exe文件安装 2.安装后将C:\Users\Administrator\.jprofiler8\config.xml文件复制到指定文件下,如: ...

  7. Javascript我学之四作用域

    本文是金旭亮老师网易云课堂的课程笔记,记录下来,以供备忘 作用域 JavaScript的变量作用域只有两种,全局作用域和函数作用域. 函数的作用域 函数中定义的变量是私有的,仅在本函数范围内有效,称为 ...

  8. drop、truncate和delete的区别

    TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行.但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源 ...

  9. 02.Control

    01.if ''' 제어문 = 조건문(if) + 반복문(while, for) 조건문 기본 형식1) python 블럭 if 조건식 : 실행문 실행문 cf) c언어 블럭 if 조건식 { ...

  10. windows下创建MySQL定时备份与删除脚本

    今天在windows服务器上面写了一个MySQL定时任务,备份呢与删除 rem *****************************Code start********************* ...