OVER(PARTITION BY)开窗函数
X 市建了一个新的体育馆,每日人流量信息被记录在这三列信息中:序号 (id)、日期 (visit_date)、 人流量 (people)。
请编写一个查询语句,找出人流量的高峰期。高峰期时,至少连续三行记录中的人流量不少于100。
例如,表 stadium:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 1 | 2017-01-01 | 10 |
| 2 | 2017-01-02 | 109 |
| 3 | 2017-01-03 | 150 |
| 4 | 2017-01-04 | 99 |
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
对于上面的示例数据,输出为:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
解题:
select id,visit_date,people from (
select id,visit_date,people,count(b)over(partition by b) b2 from (
select *,(id-row_number()over(order by id)) as b
from stadium where people >= 100
) t1
) t2
where b2>=3;
over(partition by)和group by 作用相同,但是group by 是聚合函数,会影响输出结果,而over(partition by)是开窗函数,会在每一行后面加上分析的结果
比如count(Id)over(partiton by),那么就会在每一行后面加一列数据,就是统计Id的数量值
------------------------------------------分割线--------------------------------------------------
排序
现有这么一个表,根据不同部门对薪水进行排序:
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Jim | 90000 | 1 |
| 3 | Henry | 80000 | 2 |
| 4 | Sam | 60000 | 2 |
| 5 | Max | 90000 | 1 |
+----+-------+--------+--------------+
现在需要对各部门每个人的工资进行排序
方法1-row_number()
select *,row_number()over(partition by DepartmentId order by Salary desc)as `Rank` from test;
+----+--------+--------+--------------+------+
| id | Name | Salary | DepartmentId | Rank |
+----+--------+--------+--------------+------+
| 2 | Jim | 90000 | 1 | 1 |
| 5 | Max | 90000 | 1 | 2 |
| 1 | Joe | 70000 | 1 | 3 |
| 3 | Henery | 80000 | 2 | 1 |
| 4 | Sam | 60000 | 2 | 2 |
+----+--------+--------+--------------+------+
直接取排序后的行数,排名不重复
方法2-rank()
select *,rank()over(partition by DepartmentId order by Salary desc)as `Rank` from test;
+----+--------+--------+--------------+------+
| id | Name | Salary | DepartmentId | Rank |
+----+--------+--------+--------------+------+
| 2 | Jim | 90000 | 1 | 1 |
| 5 | Max | 90000 | 1 | 1 |
| 1 | Joe | 70000 | 1 | 3 |
| 3 | Henery | 80000 | 2 | 1 |
| 4 | Sam | 60000 | 2 | 2 |
+----+--------+--------+--------------+------+
相同薪水相同部门排名一样,且会空出名次
方法3-dense_rank()
select *,dense_rank()over(partition by DepartmentId order by Salary desc)as `Rank` from test;
+----+--------+--------+--------------+------+
| id | Name | Salary | DepartmentId | Rank |
+----+--------+--------+--------------+------+
| 2 | Jim | 90000 | 1 | 1 |
| 5 | Max | 90000 | 1 | 1 |
| 1 | Joe | 70000 | 1 | 2 |
| 3 | Henery | 80000 | 2 | 1 |
| 4 | Sam | 60000 | 2 | 2 |
+----+--------+--------+--------------+------+
相同薪水相同名次,不会空出名次
以上这三种方法,基本可以满足工作中所有的排序需求了