
# Top-N
#### 功能描述
Top-N 查询是根据列排序找到N个最大或最小的值。最大值集和最小值集都被视为是一种 Top-N 的查询。如果在批处理或流处理的表中需要显示出满足条件的 N 个最底层记录或最顶层记录， Top-N 查询将会十分有用。
#### 语法格式
```
SELECT [column_list]
FROM (
   SELECT [column_list],
     ROW_NUMBER() OVER ([PARTITION BY col1[, col2...]]
       ORDER BY col1 [asc|desc][, col2 [asc|desc]...]) AS rownum
   FROM table_name)
WHERE rownum <= N [AND conditions]
```
#### 语法说明
- ROW_NUMBER(): 根据当前分区内的各行的顺序从第一行开始，依次为每一行分配一个唯一且连续的号码。目前，我们只支持 ROW_NUMBER 在 over 窗口函数中使用。未来将会支持 RANK() 和 DENSE_RANK()函数。
- PARTITION BY col1\[, col2...\]: 指定分区列，每个分区都将会有一个 Top-N 结果。
- ORDER BY col1 \[asc\|desc\]\[, col2 \[asc\|desc\]...\]: 指定排序列，不同列的排序方向可以不一样。
- WHERE rownum \<= N: Flink 需要 rownum \<= N 才能识别一个查询是否为 Top-N 查询。 其中， N 代表最大或最小的 N 条记录会被保留。
- \[AND conditions\]: 在 where 语句中，可以随意添加其他的查询条件，但其他条件只允许通过 AND 与 rownum \<= N 结合使用。
 
#### 注意事项
- TopN 查询的结果会带有更新。
- Flink SQL 会根据排序键对输入的流进行排序。
- 如果 top N 的记录发生了变化，变化的部分会以撤销、更新记录的形式发送到下游。
- 如果 top N 记录需要存储到外部存储，则结果表需要拥有相同与 Top-N 查询相同的唯一键。
 
#### 示例
查询每个分类实时销量最大的五个产品
```
SELECT * 
  FROM ( 
     SELECT *,
         ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) as row_num
     FROM ShopSales)
  WHERE row_num <= 5;
```
