# 窗口函数

__*窗口函数*__
__*RANK 函数*__

+ 窗口函数为结果集中的每个输入的记录计算输出
+ 除了示例中的 **RANK()**, TiDB 支持的窗口函数还有:
  + `CUME_DIST(), DENSE_RANK(), FIRST_VALUE(), LAG(), LAST_VALUE(), LEAD(), NTH_VALUE(), NTITLE(), PERCENT_RANK(), ROW_NUMER()`
```8
tidb> SELECT
    -> name, mass, gravity,
    -> ~!@rank() over (partition by category_id order by mass desc)@!~ as mass_rank_within_category
    -> FROM universe.planets;
+--------------------+--------+---------+---------------------------+
| name               | mass   | gravity | mass_rank_within_category |
+--------------------+--------+---------+---------------------------+
| Pluto              |  0.013 |     0.7 |                         1 |
| Jupiter            |   1898 |    23.1 |                         1 |
| Saturn             |    568 |     9.0 |                         2 |
| Neptune            |    102 |    11.0 |                         3 |
| Uranus             |   86.8 |     8.7 |                         4 |
| Proxima Centauri b | 7.5819 |    11.3 |                         1 |
| Earth              |   5.97 |     9.8 |                         2 |
| Venus              |   4.87 |     8.9 |                         3 |
| Mars               |  0.642 |     3.7 |                         4 |
| Mercury            |   0.33 |     3.7 |                         5 |
+--------------------+--------+---------+---------------------------+
10 rows in set (0.01 sec)
```
-----------------------------------------------------------------------
- TiDB 中窗口函数的使用方法与 MySQL 8.0 基本一致,由于窗口函数会使用一些保留关键字,可能导致原先可以正常执行的 SQL 语句在升级 TiDB 后无法被解析语法,此时可以将 tidb_enable_window_function 设置为 0,该参数的默认值为 1。

- TiDB 支持的窗口函数如下所示:
  - `CUME_DIST()`	返回一组值中的累积分布
  - `DENSE_RANK()`	返回分区中当前行的排名,并且排名是连续的
  - `FIRST_VALUE()`	当前窗口中第一行的表达式值
  - `LAG()`	        分区中当前行前面第 N 行的表达式值
  - `LAST_VALUE()`	当前窗口中最后一行的表达式值
  - `LEAD()`	    分区中当前行后面第 N 行的表达式值
  - `NTH_VALUE()`	当前窗口中第 N 行的表达式值
  - `NTILE()`	    将分区划分为 N 桶,为分区中的每一行分配桶号
  - `PERCENT_RANK()`返回分区中小于当前行的百分比
  - `RANK()`	    返回分区中当前行的排名,排名可能不连续
  - `ROW_NUMBER()`	返回分区中当前行的编号

- 例如,在返回的记录上标记行号(涉及到子查询的知识将在其他章节讲解):
```
tidb> SELECT ROW_NUMBER() OVER(), name, mass
    -> FROM
    ->   (SELECT name, mass
    ->    FROM universe.planets
    ->    ORDER BY mass DESC) v; 
+---------------------+--------------------+--------+
| ROW_NUMBER() OVER() | name               | mass   |
+---------------------+--------------------+--------+
|                   1 | Jupiter            |   1898 |
|                   2 | Saturn             |    568 |
|                   3 | Neptune            |    102 |
|                   4 | Uranus             |   86.8 |
|                   5 | Proxima Centauri b | 7.5819 |
|                   6 | Earth              |   5.97 |
|                   7 | Venus              |   4.87 |
|                   8 | Mars               |  0.642 |
|                   9 | Mercury            |   0.33 |
|                  10 | Pluto              |  0.013 |
+---------------------+--------------------+--------+
10 rows in set (0.00 sec)
```