当前位置:   article > 正文

5分钟了解什么是SQL窗口函数_什么是sql的窗口函数

什么是sql的窗口函数

窗口函数的概述

窗口函数 (开窗函数),也叫OLAP函数 (OnlineAnallytical Processing,联机分析处理,可以对数据库据

进行实时分析处理。简单来说,窗口函数指的是over()函数, 它相当于给表新增一列, 至于新增的内容

是什么, 取决于窗口函数, 结合什么函数一起使用.

窗口函数的格式

可以结合窗口函数一起使用的函数 over(partition by 分组字段 order by 排序字段 asc | desc rows

between 起始行 and 结束行)

窗口函数的参数解释

1. partition by类似千聚合函数中的 group by句子,但是在窗口函数中,要写成partition by

2 order by:和普通查询语句中的 ORDER BY没什么不同

窗口函数的分类

聚合函数: count(), sum(), max(), min(), avg()

排序函数: row_number(), rank(), dense_rank(), ntile(数字)

其它函数: lag(), lead(), first_value(), last_value()

细节:

1. 窗口函数, 相当于给表新增一列, 至于新增内容是什么, 取决于窗口函数, 结合什么函数一起使用.

2. 如果不写partition by, 则是全局统计, 如果写了, 则是局部统计(即: 只统计该分组的数据)

3. 如果不写order by, 则统计组内所有的数据, 如果写了, 则统计组内第一行 至 当前行的数据.

4. rows between ... and...可以指定操作行的范围, 包左包右,

涉及到的关键字如下:

        unbounded preceding # 表示: 第1行.

        n preceding # 向上的n行

        current row # 当前行.

        n following # 向下的n行

        unbounded following # 表示: 最后1行.

5. ntile(数字) 表示把数据分成几份, 即: 几分之几, 优先参考最小分区. 例如: 7条数据, 操作之后, 就

是: 1, 1, 1 2, 2 3, 3

以下使用代码实现

数据准备
  1. # 员工表
  2. CREATE TABLE employee
  3. (
  4. id int, # 编号
  5. name varchar(20), # 姓名
  6. deg varchar(20), # 职位
  7. salary int, # 工资
  8. dept varchar(20) # 部门
  9. );
  10. insert into employee value (1201, 'gopal', 'manager', 50000, 'TP');
  11. insert into employee value (1202, 'manisha', 'cto', 50000, 'TP');
  12. insert into employee value (1203, 'khalil', 'dev', 30000, 'AC');
  13. insert into employee value (1204, 'prasanth', 'dev', 30000, 'AC');
  14. insert into employee value (1206, 'kranthi', 'admin', 20000, 'TP');
  15. # 网站点击量表
  16. create table website_pv_info
  17. (
  18. cookieid varchar(20), # 用户id
  19. createtime varchar(20), # 访问时间
  20. pv int # 页面浏览量
  21. );
  22. insert into website_pv_info value ('cookie1', '2018-04-10', 1);
  23. insert into website_pv_info value ('cookie1', '2018-04-11', 5);
  24. insert into website_pv_info value ('cookie1', '2018-04-12', 7);
  25. insert into website_pv_info value ('cookie1', '2018-04-13', 3);
  26. insert into website_pv_info value ('cookie1', '2018-04-14', 2);
  27. insert into website_pv_info value ('cookie1', '2018-04-15', 4);
  28. insert into website_pv_info value ('cookie1', '2018-04-16', 4);
  29. insert into website_pv_info value ('cookie2', '2018-04-10', 2);
  30. insert into website_pv_info value ('cookie2', '2018-04-11', 3);
  31. insert into website_pv_info value ('cookie2', '2018-04-12', 5);
  32. insert into website_pv_info value ('cookie2', '2018-04-13', 6);
  33. insert into website_pv_info value ('cookie2', '2018-04-14', 3);
  34. insert into website_pv_info value ('cookie2', '2018-04-15', 9);
  35. insert into website_pv_info value ('cookie2', '2018-04-16', 7);
  36. # 网站访问记录表
  37. create table website_url_info
  38. (
  39. cookieid varchar(20), # 用户id
  40. createtime varchar(20), # 访问时间
  41. url varchar(20) # 访问的url页面
  42. );
  43. insert into website_url_info value ('cookie1', '2018-04-10 10:00:02', 'url2');
  44. insert into website_url_info value ('cookie1', '2018-04-10 10:00:00', 'url1');
  45. insert into website_url_info value ('cookie1', '2018-04-10 10:03:04', '1url3');
  46. insert into website_url_info value ('cookie1', '2018-04-10 10:50:05', 'url6');
  47. insert into website_url_info value ('cookie1', '2018-04-10 11:00:00', 'url7');
  48. insert into website_url_info value ('cookie1', '2018-04-10 10:10:00', 'url4');
  49. insert into website_url_info value ('cookie1', '2018-04-10 10:50:01', 'url5');
  50. insert into website_url_info value ('cookie2', '2018-04-10 10:00:02', 'url22');
  51. insert into website_url_info value ('cookie2', '2018-04-10 10:00:00', 'url11');
  52. insert into website_url_info value ('cookie2', '2018-04-10 10:03:04', '1url33');
  53. insert into website_url_info value ('cookie2', '2018-04-10 10:50:05', 'url66');
  54. insert into website_url_info value ('cookie2', '2018-04-10 11:00:00', 'url77');
  55. insert into website_url_info value ('cookie2', '2018-04-10 10:10:00', 'url44');
  56. insert into website_url_info value ('cookie2', '2018-04-10 10:50:01', 'url55');
窗口函数初体验
  1. # 案例1: 窗口函数初体验.
  2. # 需求: 统计每个所有员工的工资, 并将其展示在每个员工数据的最后.
  3. # 思路1: 聚合函数直接实现, 能计算出: 所有员工的工资总和, 但是无法达到想要的效果.
  4. select *, sum(salary) as total_salary from employee;
  5. # 思路2: 窗口函数可以实现我们要的效果.
  6. select *, sum(salary) over() as total_salary from employee;
  7. select * from employee;
窗口 + 聚合
  1. # 案例2: 演示 窗口函数 + 聚合函数一起使用.
  2. # 需求:求出网站总的pv数 所有用户所有访问加起来
  3. select *, sum(pv) over() from website_pv_info; # 不写partition by, 全局统计(统计表中所有的数据)
  4. # 需求: 求出每个用户总pv数
  5. # 方式1: sum() + group by 一起使用.
  6. select cookieid, sum(pv) as total_pv from website_pv_info group by cookieid;
  7. # 方式2: 聚合函数 + 窗口函数一起使用.
  8. select *, sum(pv) over(partition by cookieid) from website_pv_info; # 写partition by, 局部统计(只统计该分组的数据.)
  9. # 演示: 如果不写order by, 则统计组内所有的数据, 如果写了, 则统计组内第一行 至 当前行的数据.
  10. select *, sum(pv) over(partition by cookieid order by createtime) from website_pv_info; # 写order by, 局部统计(统计组内第一行 至 当前行的内容)
  11. # 上述的代码, 等同于:
  12. select
  13. *,
  14. sum(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row ) as n1 # 起始行 到 当前行
  15. from website_pv_info; # 写order by, 局部统计(统计组内第一行 至 当前行的内容)
  16. # 需求: 统计每个cookieID的pv(访问量), 只统计: 当前行及 向前3行 向后1行
  17. select
  18. *,
  19. sum(pv) over(partition by cookieid order by createtime rows between 3 preceding and 1 following)
  20. from website_pv_info; # 写order by, 局部统计(统计组内第一行 至 当前行的内容)
窗口 + 排序
  1. # 需求: 根据点击量(pv)做排名. 根据cookieid分组, 根据点击量降序排名.
  2. select
  3. *,
  4. # 根据cookieid分组, 根据点击量降序排名.
  5. row_number() over(partition by cookieid order by pv desc) as rn, # 例如: 排名为: 1, 2, 3, 4
  6. rank() over(partition by cookieid order by pv desc) as rk, # 例如: 排名为: 1, 2, 2, 4
  7. dense_rank() over(partition by cookieid order by pv desc) as dr # 例如: 排名为: 1, 2, 2, 3
  8. from website_pv_info;
  9. # ntile(数字,表示分成几份) 采用均分策略, 每份之间的差值不超过1, 优先参考最小的那个部分, 即: 7分成3份, 则是: 3, 2, 2
  10. select
  11. *,
  12. # 根据cookieid分组, 根据点击量降序排名.
  13. ntile(3) over(partition by cookieid order by pv desc) as nt
  14. from website_pv_info;
  15. # 上述的ntile()是将数据分成指定的 份数, 方便我们取样(采样), 例如: 将数据按组分成5份, 只获取每组的第1份数据, 则计算量的数据量至少降低 5 倍.
  16. # 例如: 上述的数据是分成了3份, 如果我要每组的第一份怎么办? 子查询.
  17. select * from (
  18. select *,
  19. # 根据cookieid分组, 根据点击量降序排名.
  20. ntile(3) over (partition by cookieid order by pv desc) as nt
  21. from website_pv_info
  22. ) t1 where t1.nt = 1;
窗口 + 其它
  1. # 1. LAG 用于统计窗口内往上第n行值
  2. select
  3. *,
  4. # 获取上一行的createtime类的值 根据cookieid分组 根据创建时间排序
  5. lag(createtime) over(partition by cookieid order by createtime)
  6. from website_url_info;
  7. # 完整写法如下
  8. select
  9. *,
  10. # lag()函数的参数解释: 参1 要操作的列, 参2: 向上的第n行, 参3: 默认值,找不到数据的时候, 用默认值填充.
  11. lag(createtime, 2, '1970-01-01 00:00:00') over(partition by cookieid order by createtime)
  12. from website_url_info;
  13. # 2. LEAD 用于统计窗口内往下第n行值
  14. select
  15. *,
  16. # LEAD()函数的参数解释: 参1 要操作的列, 参2: 向上的第n行, 参3: 默认值,找不到数据的时候, 用默认值填充.
  17. LEAD(createtime, 2, '1970-01-01 00:00:00') over(partition by cookieid order by createtime)
  18. from website_url_info;
  19. # 3. FIRST_VALUE 取分组内排序后,截止到当前行,第一个值
  20. select
  21. *,
  22. first_value(createtime) over(partition by cookieid order by createtime)
  23. from website_url_info;
  24. # 4. LAST_VALUE 取分组内排序后,截止到当前行,最后一个值
  25. select
  26. *,
  27. last_value(createtime) over(partition by cookieid order by createtime)
  28. from website_url_info;

总结

1.窗口函数的功能
        ①同时具有分组 (partition by)和排序 (order by)的功能
        ② 不减少原表的行数
2.窗口函数的执行顾序
        在使用over等开窗函数时,over(里的分组以及排序的执行,晚于 where、group by、 order         by的执行。
3. 窗口函数的使用场景
        ①组内排名
        ②求占比
        ③ TopN问题
4. 注意事项
        ①窗口函数原则上只能写在select子句中。
        ②partition子句原则上可是省略,省略就是 不指定分组。但是,这就失去了窗口函数的功能,所以一般不要这么使用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/894259
推荐阅读
相关标签
  

闽ICP备14008679号