【原创】MySQL 以及 Python 实现排名窗口函数

大部分数据库都提供了窗口函数,比如RANK,ROW_NUMBER等等。 MySQL 这方面没有直接提供,但是可以变相的实现,我以前写了row_number 的实现,今天有时间把 rank 的实现贴出来。

这里,我用MySQL 以及Python 分别实现了rank 窗口函数。

原始表信息:

t_girl=# \d group_concat;
           Table "ytt.group_concat"
  Column  |         Type          | Modifiers
----------+-----------------------+-----------
 rank     | integer               |
 username | character varying(20) |

表数据

t_girl=# select * from group_concat;
 rank | username
------+----------
  100 | Lucy
  127 | Lucy
  146 | Lucy
  137 | Lucy
  104 | Lucy
  121 | Lucy
  136 | Lily
  100 | Lily
  100 | Lily
  105 | Lily
  136 | Lily
  149 | ytt
  116 | ytt
  116 | ytt
  149 | ytt
  106 | ytt
  117 | ytt
(17 rows)
Time: 0.638 ms

PostgreSQL 的rank 窗口函数示例:

t_girl=# select username,rank,rank() over(partition by username order by rank desc) as rank_cnt from group_concat;
 username | rank | rank_cnt
----------+------+----------
 Lily     |  136 |        1
 Lily     |  136 |        1
 Lily     |  105 |        3
 Lily     |  100 |        4
 Lily     |  100 |        4
 Lucy     |  146 |        1
 Lucy     |  137 |        2
 Lucy     |  127 |        3
 Lucy     |  121 |        4
 Lucy     |  104 |        5
 Lucy     |  100 |        6
 ytt      |  149 |        1
 ytt      |  149 |        1
 ytt      |  117 |        3
 ytt      |  116 |        4
 ytt      |  116 |        4
 ytt      |  106 |        6
(17 rows)
Time: 131.150 ms

MySQL 提供了group_concat 聚合函数可以变相的实现:

mysql>
select a.username, a.rank, find_in_set(a.rank,b.rank_gp) as rank_cnt
from group_concat as a ,
(select username,group_concat(rank order by rank desc separator ‘,‘)  as rank_gp from group_concat group by username
) b
where a.username = b.username order by a.username asc,a.rank desc;
+----------+------+----------+
| username | rank | rank_cnt |
+----------+------+----------+
| Lily     |  136 |        1 |
| Lily     |  136 |        1 |
| Lily     |  105 |        3 |
| Lily     |  100 |        4 |
| Lily     |  100 |        4 |
| Lucy     |  146 |        1 |
| Lucy     |  137 |        2 |
| Lucy     |  127 |        3 |
| Lucy     |  121 |        4 |
| Lucy     |  104 |        5 |
| Lucy     |  100 |        6 |
| ytt      |  149 |        1 |
| ytt      |  149 |        1 |
| ytt      |  117 |        3 |
| ytt      |  116 |        4 |
| ytt      |  116 |        4 |
| ytt      |  106 |        6 |
+----------+------+----------+
17 rows in set (0.02 sec)

当然了,如果MySQL SQL不太熟悉,可以用程序来处理,比如我下面用python 实现了rank 函数,执行结果如下:(脚本源代码最后)

>>> ================================ RESTART ================================
>>>
 username |   rank   | rank_cnt
--------------------------------
ytt       |149       |1
ytt       |149       |1
ytt       |117       |3
ytt       |116       |4
ytt       |116       |4
ytt       |106       |6
Lucy      |146       |1
Lucy      |137       |2
Lucy      |127       |3
Lucy      |121       |4
Lucy      |104       |5
Lucy      |100       |6
Lily      |136       |1
Lily      |136       |2
Lily      |105       |3
Lily      |100       |4
Lily      |100       |4
(17 Rows.)
Time:     0.162 Seconds.

附上脚本代码:

from __future__ import print_function
from datetime import date, datetime, timedelta
import mysql.connector
import time
# Created by ytt 2014/5/14.
# Rank function implement.
def db_connect(is_true):
    cnx = mysql.connector.connect(host=‘192.168.1.131‘,port=‘3306‘,user=‘python_user‘, password=‘python_user‘,database=‘t_girl‘,autocommit=is_true)
    return cnx
def db_rs_rank(c1 =‘username desc‘ ,c2 = ‘ rank desc‘):
    # c1: partition column.
    # c2: sort column.
    time_start = time.time()
    cnx = db_connect(True)
    rs = cnx.cursor()
    query0 = "select username,rank from group_concat order by " + c1 + ", " + c2
    rs.execute(query0,multi=False)
    if rs.with_rows:
        rows = rs.fetchall()
    else:
        return "No rows affected."
    i = 0
    j = 0
    k = 1
    result = []
    field1_compare = rows[0][0]
    field2_compare = rows[0][1]
    while i < len(rows):
        if field1_compare == rows[i][0]:
            j += 1
            if field2_compare != rows[i][1]:
                field2_compare =rows[i][1]
                k = j
            result.append((rows[i][0],rows[i][1],k))
        else:
            j = 1
            k = 1
            field1_compare = rows[i][0]
            result.append((rows[i][0],rows[i][1],k))
        i += 1
    i = 0
    rows_header = list(rs.column_names)
    rows_header.append(‘rank_cnt‘)
    print (rows_header[0].center(10,‘ ‘) + ‘|‘ + rows_header[1].center(10,‘ ‘) + ‘|‘ + rows_header[2].center(10,‘ ‘))
    print (‘-‘.center(32,‘-‘))
    while i < len(result):
        print (result[i][0].ljust(10,‘ ‘) + ‘|‘ + str(result[i][1]).ljust(10,‘ ‘) + ‘|‘ + str(result[i][2]).ljust(10,‘ ‘))
        i += 1
    rs.close()
    cnx.close()
    time_end = time.time()
    print (‘(‘ + str(len(rows))+ ‘ Rows.)‘)
    print ("Time:" + str(round((time_end-time_start),3)).rjust(10,‘ ‘) + ‘ Seconds.‘)
if __name__==‘__main__‘:
    db_rs_rank()

【原创】MySQL 以及 Python 实现排名窗口函数

时间: 2024-12-23 17:55:49

【原创】MySQL 以及 Python 实现排名窗口函数的相关文章

MySQL 以及 Python 实现排名窗口函数

大部分数据库都提供了窗口函数,比如RANK,ROW_NUMBER等等. MySQL 这方面没有直接提供,但是可以变相的实现,我以前写了row_number 的实现,今天有时间把 rank 的实现贴出来. 这里,我用MySQL 以及Python 分别实现了rank 窗口函数.原始表信息: t_girl=# \d group_concat; Table "ytt.group_concat" Column | Type | Modifiers ----------+-------------

在Ubuntu上安装Mysql For Python

安装: 首先安装pip,并且把pip更新到最小版本 apt-get install python-pip pip install -U pip 安装mysql开发包 apt-get install python-dev libmysqlclient-dev 通过pip安装Mysql For Python pip install MySQL-python 测试,在Python命令行里输入import MySQLdb,看报不报错 [email protected]:~$ python Python

Installing MySQL Connector/Python using pip v1.5

The latest pip versions will fail on you when the packages it needs to install are not hosted on PyPI . When you try to install MySQL Connector/Python the usually way, you get following message is: shell> pip install mysql-connector-python Could not

MySQL Connector/Python 开发者指南

本文翻译自:https://dev.mysql.com/doc/connector-python/en/ 摘要 这篇手册描述了怎么来安装和配置 MySQL Connector/Python,MySQL Connector/Python 是 Python 和 MySQL 服务进行通信的一个独立驱动程序,本篇手册还将阐述如何利用它来开发数据库应用程序. 获取 Connector/Python 的每一次发布版本的改动细节,请参阅 MySQL Connector/Python Release Notes

Snippet: Fetching results after calling stored procedures using MySQL Connector/Python

https://geert.vanderkelen.org/2014/results-after-procedure-call/ Problem Using MySQL Connector/Python, you are calling a stored procedure which is also selecting data and you would like to fetch the rows of the result. Solution For this example we cr

MSSQL示例(三)ROWNUMBER、RANK、DENSE_RANK、NTILE排名窗口函数示例

-- ============================================= -- Author:  tomtom -- Create date: 2015.2.27 -- Description: ROWNUMBER.RANK.DENSE_RANK.NTILE排名窗口函数示例 -- ============================================= /*1.准备数据(去掉注释再执行--!) create table t1 ( id int ident

_mysql.c(42) : fatal error C1083: Cannot open include file: &#39;config-win.h&#39;:问题的解决 mysql安装python

在win7下安装了Python后,想安装python-MySQL,使用pip安装出现如下问题: >pip install MySQL-python _mysql.c(42) : fatal error C1083: Cannot open include file: 'config-win.h': No such file or directory error: command '"C:\Users\fnngj\AppData\Local\Programs\Common\Microsoft

#MySQL for Python(MySQLdb) Note

#MySQL for Python(MySQLdb) Note #切记不要在python中创建表,只做增删改查即可. #步骤:(0)引用库 -->(1)创建连接 -->(2)创建游标 -->(3)选择数据库 -->(4)执行语句 -->(5)关闭连接 #(0)引用库 import MySQLdb #(1)创建连接 con = MySQLdb.connect(user = "root", passwd = "123456",host =

How to Access MySQL with Python Version 3.4

http://askubuntu.com/questions/630728/how-to-access-mysql-with-python-version-3-4 How to Access MySQL with Python Version 3.4 up vote0down votefavorite Python comes in two versions: Python 2.7.6 which has now been superseded by Python 3.4.0. The crit