mysql實現開窗函數

mysql實現開窗函數

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

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

準備數據

# 建表
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測試

相關文章
相關標籤/搜索