Hive数仓操作(十五)

Hive 开窗函数

Hive窗口函数是一种特殊的函数,允许用户在查询中对一组行进行计算,而不仅仅是单独的行。窗口函数可以在 SQL 查询中进行聚合、排名、累积计算等。这使得窗口函数在数据分析和报告生成中非常有用。

窗口函数的基本组成部分

  1. 函数类型 :如 ROW_NUMBER(), RANK(), DENSE_RANK(), SUM(), AVG() 等。
  2. OVER 子句:定义窗口的范围和分区,用于指定在哪些行上应用窗口函数。

窗口边界标识符

  1. CURRENT ROW:

    • 表示窗口的当前行。通常用于窗口的结束范围。
  2. n PRECEDING:

    • 表示当前行之前的n行。例如,ROWS BETWEEN 1 PRECEDING AND CURRENT ROW 表示从当前行向上看一行到当前行。
  3. n FOLLOWING:

    • 表示当前行之后的n行。例如,ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING 表示从当前行到当前行的后两行。
  4. UNBOUNDED:

    • 表示没有边界,通常用于定义窗口的起点或终点。
  5. UNBOUNDED PRECEDING:

    • 表示从窗口的起点开始,不限行数。
  6. UNBOUNDED FOLLOWING:

    • 表示到窗口的终点结束,不限行数。

窗口边界函数

  1. LAG(col, n):

    • 这个函数用于获取当前行的前n行中的指定列的值。它可以用于比较当前行与前几行的数据。
    sql 复制代码
    SELECT 
        employee_id, 
        salary, 
        LAG(salary, 1) OVER (ORDER BY employee_id) AS previous_salary
    FROM 
        employees;

    这个示例显示了每个员工的当前工资和前一个员工的工资。

  2. LEAD(col, n):

    • 这个函数用于获取当前行的后n行中的指定列的值。与 LAG 类似,但它是向下查找。
    sql 复制代码
    SELECT 
        employee_id, 
        salary, 
        LEAD(salary, 1) OVER (ORDER BY employee_id) AS next_salary
    FROM 
        employees;

    这个示例显示了每个员工的当前工资和下一个员工的工资。

示例数据集

假设我们有一个名为 business 的表,内容如下:

name orderdate cost
Alice 2017-04-01 100
Bob 2017-04-05 150
Alice 2017-04-10 200
Charlie 2017-05-01 300
Bob 2017-05-10 100
Alice 2017-05-15 250
Charlie 2017-06-01 400

SQL 查询运行结果

1. 查询在2017年4月份购买过的顾客及总人数

sql 复制代码
SELECT name, COUNT(*) OVER() 
FROM business
WHERE SUBSTRING(orderdate, 1, 7) = '2017-04';

结果:

name COUNT(*)
Alice 3
Bob 3
Alice 3
2. 查询顾客的购买明细及月购买总额

顾客购买明细及购买总额:

sql 复制代码
SELECT name, orderdate, cost, SUM(cost) OVER() 
FROM business;

结果:

name orderdate cost SUM(cost)
Alice 2017-04-01 100 1300
Bob 2017-04-05 150 1300
Alice 2017-04-10 200 1300
Charlie 2017-05-01 300 1300
Bob 2017-05-10 100 1300
Alice 2017-05-15 250 1300
Charlie 2017-06-01 400 1300

明细及月购买总额:

sql 复制代码
SELECT name, orderdate, cost, SUM(cost) OVER(PARTITION BY MONTH(orderdate)) 
FROM business;

结果:

name orderdate cost SUM(cost)
Alice 2017-04-01 100 300
Bob 2017-04-05 150 300
Alice 2017-04-10 200 300
Charlie 2017-05-01 300 700
Bob 2017-05-10 100 700
Alice 2017-05-15 250 700
Charlie 2017-06-01 400 400

顾客购买明细及顾客购买总额:

sql 复制代码
SELECT name, orderdate, cost, SUM(cost) OVER(PARTITION BY name) 
FROM business;

结果:

name orderdate cost SUM(cost)
Alice 2017-04-01 100 550
Bob 2017-04-05 150 250
Alice 2017-04-10 200 550
Charlie 2017-05-01 300 700
Bob 2017-05-10 100 250
Alice 2017-05-15 250 550
Charlie 2017-06-01 400 400

顾客购买明细及顾客月购买总额:

sql 复制代码
SELECT name, orderdate, cost, SUM(cost) OVER(PARTITION BY name, MONTH(orderdate)) 
FROM business;

结果:

name orderdate cost SUM(cost)
Alice 2017-04-01 100 300
Bob 2017-04-05 150 150
Alice 2017-04-10 200 300
Charlie 2017-05-01 300 300
Bob 2017-05-10 100 100
Alice 2017-05-15 250 250
Charlie 2017-06-01 400 400
3. 按照日期进行累加

按照日期逐步累加购买总额

sql 复制代码
SELECT name, orderdate, cost,
SUM(cost) OVER(PARTITION BY name ORDER BY orderdate) 
FROM business;

方法2(边界从起点到当前行):

sql 复制代码
SELECT name, orderdate, cost,
SUM(cost) OVER(PARTITION BY name ORDER BY orderdate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sample4
FROM business;

结果:

name orderdate cost SUM(cost)
Alice 2017-04-01 100 100
Alice 2017-04-10 200 300
Alice 2017-05-15 250 550
Bob 2017-04-05 150 150
Bob 2017-05-10 100 250
Charlie 2017-05-01 300 300
Charlie 2017-06-01 400 700

当前行和前面一行的聚合:

sql 复制代码
SELECT name, orderdate, cost,
SUM(cost) OVER(PARTITION BY name ORDER BY orderdate ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS sample5
FROM business;

结果:

name orderdate cost sample5
Alice 2017-04-01 100 100
Alice 2017-04-10 200 300
Alice 2017-05-15 250 450
Bob 2017-04-05 150 150
Bob 2017-05-10 100 250
Charlie 2017-05-01 300 300
Charlie 2017-06-01 400 400

当前行和前后各一行的聚合:

sql 复制代码
SELECT name, orderdate, cost,
SUM(cost) OVER(PARTITION BY name ORDER BY orderdate ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sample6
FROM business;

结果:

name orderdate cost sample6
Alice 2017-04-01 100 300
Alice 2017-04-10 200 550
Alice 2017-05-15 250 250
Bob 2017-04-05 150 250
Bob 2017-05-10 100 100
Charlie 2017-05-01 300 700
Charlie 2017-06-01 400 400

当前行及后面所有行:

sql 复制代码
SELECT name, orderdate, cost,
SUM(cost) OVER(PARTITION BY name ORDER BY orderdate ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS sample7
FROM business;

结果:

name orderdate cost sample7
Alice 2017-04-01 100 550
Alice 2017-04-10 200 250
Alice 2017-05-15 250 250
Bob 2017-04-05 150 100
Bob 2017-05-10 100 100
Charlie 2017-05-01 300 400
Charlie 2017-06-01 400 400
4. 查询顾客上次的购买时间

使用 LAG 函数:

sql 复制代码
SELECT name, orderdate, cost,
LAG(orderdate, 1) OVER(PARTITION BY name ORDER BY orderdate) AS last_purchase_date
FROM business;

结果:

name orderdate cost last_purchase_date
Alice 2017-04-01 100 NULL
Alice 2017-04-10 200 2017-04-01
Alice 2017-05-15 250 2017-04-10
Bob 2017-04-05 150 NULL
Bob 2017-05-10 100 2017-04-05
Charlie 2017-05-01 300 NULL
Charlie 2017-06-01 400 2017-05-01
相关推荐
纪伊路上盛名在13 分钟前
爬虫1:uniprot蛋白质序列数据+canvas图片
数据库·学习·知识图谱·学习方法
程序员黄同学2 小时前
如何使用 Python 连接 MySQL 数据库?
数据库·python·mysql
新手小袁_J3 小时前
实现Python将csv数据导入到Neo4j
数据库·python·neo4j·《我是刑警》·python连接neo4j·python导入csv·csv数据集导入neo4j
シ風箏3 小时前
Neo4j【环境部署 02】图形数据库Neo4j在Linux系统ARM架构下的安装使用
linux·数据库·arm·neo4j
张声录13 小时前
【ETCD】【实操篇(四)】etcd常见问题快问快答FAQ
数据库·etcd
CherishTaoTao5 小时前
sqlite基础
数据库·oracle·sqlite
嶔某6 小时前
MySql:基本查询
数据库·mysql
开心工作室_kaic8 小时前
springboot461学生成绩分析和弱项辅助系统设计(论文+源码)_kaic
开发语言·数据库·vue.js·php·apache
不会写代码的女程序猿8 小时前
关于ETL的两种架构(ETL架构和ELT架构)
数据仓库·架构·etl
毕设资源大全8 小时前
基于SpringBoot+html+vue实现的林业产品推荐系统【源码+文档+数据库文件+包部署成功+答疑解惑问到会为止】
java·数据库·vue.js·spring boot·后端·mysql·html