mysql實現開窗函式

2021-09-07 15:56:55 字數 3213 閱讀 6637

mysql實現開窗函式

學習過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 開窗函式 累加 mysql實現開窗函式

學習過oracle的應該知道,oracle中的分析函式功能十分強大,包括mssql postgresql等資料庫都支援開窗函式。然而mysql至今都沒有提供這樣的功能,今天就來 下用mysql實現一些開窗功能需求。實驗資料 表sale month user id amount 201601 1 50...

MySql實現ROW NUMBER 開窗函式

本文咱們使用mysql實現開窗函式row number over partition by order by 廢話不多說,直接開幹 準備資料select from test biz policy policy platform id 平台id publish time 政策發布時間 policy n...

MySQL中實現開窗函式

一 概述 row number是資料庫中常用的乙個開窗函式,可以實現資料分割槽編號的功能,然而mysql並不支援開窗函式。本文介紹了在mysql中實現開窗函式的方法。二 經典開窗函式 首先準備基礎資料,如下入所示。在hive或oracle中使用經典開窗函式實現資料分組編號的方法如下。select n...