mysql實現開窗函數


mysql實現開窗函數

開窗分析函數簡單來說就是類似partition by aaa, bbb order by ccc這樣的形式

在使用mysql的過程中遇到過這樣的需求,需要求出一段時間內每個item的最大值及對應的那一條記錄。最大值很容易使用group by item求出來,但是求出那一條對應的所有字段及值卻不好實現。經過查資料及探索發現mysql也可以實現,思路是人為構造一個字段來標記順序,這樣不僅能實現最大,還能實現TOP N。記錄下簡單示例:

准備數據

# 建表
CREATE TABLE `policy_summary` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `policy_name` varchar(18) COLLATE utf8_bin DEFAULT NULL,
  `publish_time` datetime DEFAULT NULL,
  `platform_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

# 插入數據
INSERT INTO `policy_summary` VALUES ('1', 'test0', '2019-04-01 15:11:00', '2');
INSERT INTO `policy_summary` VALUES ('2', 'test9', '2019-04-01 19:11:00', '2');
INSERT INTO `policy_summary` VALUES ('3', 'test8', '2019-04-01 19:11:00', '2');
INSERT INTO `policy_summary` VALUES ('4', 'test7', '2019-04-01 18:11:00', '2');
INSERT INTO `policy_summary` VALUES ('5', 'test1', '2019-04-01 15:11:00', '2');
INSERT INTO `policy_summary` VALUES ('6', 'test2', '2019-04-01 15:11:00', '2');
INSERT INTO `policy_summary` VALUES ('7', 'test3', '2019-04-01 16:11:00', '2');
INSERT INTO `policy_summary` VALUES ('8', 'test4', '2019-04-01 16:11:00', '2');
INSERT INTO `policy_summary` VALUES ('9', 'test5', '2019-04-01 16:11:00', '2');
INSERT INTO `policy_summary` VALUES ('10', 'test6', '2019-04-01 17:11:00', '2');
INSERT INTO `policy_summary` VALUES ('11', 'fengyu', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('12', '新建政策1111111', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('13', '1218測試', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('14', 'xxx', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('15', 'ccc', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('16', '測試114', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('17', '測試mmm', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('18', 'kkkkkkk', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('19', 'kkkkkkk明明', '2019-04-02 19:17:00', '8');
INSERT INTO `policy_summary` VALUES ('20', 'ceshi111', '2019-04-02 19:17:00', '8');

# 查看
mysql> select * from policy_summary;
+----+-----------------+---------------------+-------------+
| id | policy_name     | publish_time        | platform_id |
+----+-----------------+---------------------+-------------+
|  1 | test0           | 2019-04-01 15:11:00 |           2 |
|  2 | test9           | 2019-04-01 19:11:00 |           2 |
|  3 | test8           | 2019-04-01 19:11:00 |           2 |
|  4 | test7           | 2019-04-01 18:11:00 |           2 |
|  5 | test1           | 2019-04-01 15:11:00 |           2 |
|  6 | test2           | 2019-04-01 15:11:00 |           2 |
|  7 | test3           | 2019-04-01 16:11:00 |           2 |
|  8 | test4           | 2019-04-01 16:11:00 |           2 |
|  9 | test5           | 2019-04-01 16:11:00 |           2 |
| 10 | test6           | 2019-04-01 17:11:00 |           2 |
| 11 | fengyu          | 2019-04-02 19:17:00 |           8 |
| 12 | 新建政策1111111 | 2019-04-02 19:17:00 |           8 |
| 13 | 1218測試        | 2019-04-02 19:17:00 |           8 |
| 14 | xxx             | 2019-04-02 19:17:00 |           8 |
| 15 | ccc             | 2019-04-02 19:17:00 |           8 |
| 16 | 測試114         | 2019-04-02 19:17:00 |           8 |
| 17 | 測試mmm         | 2019-04-02 19:17:00 |           8 |
| 18 | kkkkkkk         | 2019-04-02 19:17:00 |           8 |
| 19 | kkkkkkk明明     | 2019-04-02 19:17:00 |           8 |
| 20 | ceshi111        | 2019-04-02 19:17:00 |           8 |
+----+-----------------+---------------------+-------------+

根據platform_id,publish_time分組並根據policy_name排序

SELECT
	a.platform_id,
	a.publish_time,
	a.policy_name,
	a.id,

IF (
	@str1 = a.platform_id
	AND @str2 = a.publish_time,
	@rank := @rank + 1,
	@rank := 1
) AS rank_no,
 @str1 := a.platform_id,
 @str2 := a.publish_time
FROM
	(
		SELECT
			platform_id,
			publish_time,
			policy_name,
			id
		FROM
			policy_summary
		ORDER BY
			platform_id,
			publish_time,
			policy_name ASC
	) a,
	(
		SELECT
			@str1 := 0,
			@str2 := NULL,
			@rank := 0
	) tmp
	
	
# 查詢結果
+-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+
| platform_id | publish_time        | policy_name     | id | rank_no | @str1 := a.platform_id | @str2 := a.publish_time |
+-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+
|           2 | 2019-04-01 15:11:00 | test0           |  1 |       1 |                      2 | 2019-04-01 15:11:00     |
|           2 | 2019-04-01 15:11:00 | test1           |  5 |       2 |                      2 | 2019-04-01 15:11:00     |
|           2 | 2019-04-01 15:11:00 | test2           |  6 |       3 |                      2 | 2019-04-01 15:11:00     |
|           2 | 2019-04-01 16:11:00 | test3           |  7 |       1 |                      2 | 2019-04-01 16:11:00     |
|           2 | 2019-04-01 16:11:00 | test4           |  8 |       2 |                      2 | 2019-04-01 16:11:00     |
|           2 | 2019-04-01 16:11:00 | test5           |  9 |       3 |                      2 | 2019-04-01 16:11:00     |
|           2 | 2019-04-01 17:11:00 | test6           | 10 |       1 |                      2 | 2019-04-01 17:11:00     |
|           2 | 2019-04-01 18:11:00 | test7           |  4 |       1 |                      2 | 2019-04-01 18:11:00     |
|           2 | 2019-04-01 19:11:00 | test8           |  3 |       1 |                      2 | 2019-04-01 19:11:00     |
|           2 | 2019-04-01 19:11:00 | test9           |  2 |       2 |                      2 | 2019-04-01 19:11:00     |
|           8 | 2019-04-02 19:17:00 | 1218測試        | 13 |       1 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | ccc             | 15 |       2 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | ceshi111        | 20 |       3 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | fengyu          | 11 |       4 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | kkkkkkk         | 18 |       5 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | kkkkkkk明明     | 19 |       6 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | xxx             | 14 |       7 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | 新建政策1111111 | 12 |       8 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | 測試114         | 16 |       9 |                      8 | 2019-04-02 19:17:00     |
|           8 | 2019-04-02 19:17:00 | 測試mmm         | 17 |      10 |                      8 | 2019-04-02 19:17:00     |
+-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+

這樣rank_no就是那個標志排序的字段,如果要求最大policy_name的記錄就只需要加一個過濾條件rank_no <= 1即可

SELECT
	t.platform_id,
	t.publish_time,
	t.policy_name,
	t.rank_no,
	t.id
FROM
	(
		SELECT
			a.id,
			a.platform_id,
			a.publish_time,
			a.policy_name,

		IF (
			@str1 = a.platform_id
			AND @str2 = a.publish_time,
			@rank := @rank + 1,
			@rank := 1
		) AS rank_no,
		@str1 := a.platform_id,
		@str2 := a.publish_time
	FROM
		(
			SELECT
				id,
				platform_id,
				publish_time,
				policy_name
			FROM
				policy_summary
			ORDER BY
				platform_id,
				publish_time,
				policy_name ASC
		) a,
		(
			SELECT
				@str1 := 0,
				@str2 := NULL,
				@rank := 0
		) tmp
	) t
WHERE
	t.rank_no <= 1

參考

https://www.jianshu.com/p/2e8a29d3d669


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM