当前位置: 首页 > article >正文

SQL 窗口函数

 窗口函数用于在不改变查询结果集行数的情况下,对每一行执行聚合计算或其他复杂的计算,可以跨行计算。

随着窗口函数的出现,无须再使用关联子查询。窗口函数的可读性很好,代码也很简洁。

1 实践

1.1 营业额年度变化

需求:查找与上一年相比营业额没有变化的年份。

图 年度营业额t_year_sales 表

-- 关联子查询
SELECT *
FROM t_year_sales y1 
WHERE sale = (SELECT sale FROM t_year_sales WHERE `year` = y1.year - 1);
-- 左连接
SELECT *
FROM (
	SELECT y1.*,y2.sale AS preSale
	FROM t_year_sales y1 
	LEFT JOIN t_year_sales y2 ON y2.`year` = y1.`year` - 1
) temp 
WHERE sale = preSale;
-- 窗口函数
SELECT *
FROM (
  SELECT *,
  MAX(sale) OVER ( ORDER BY `year` RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING ) AS preSale
  FROM t_year_sales 
) temp 
WHERE sale = preSale;

1.1.1 时间轴有间断时:和过去最临近的时间进行比较

图 有间断的年度营业额t_year_sales2 表

需求:查询与过去最临近的年份营业额相同的年份。

-- 关联子查询 
SELECT *
FROM t_year_sales2 y
WHERE sale = (SELECT sale FROM t_year_sales2 WHERE `year` = (SELECT MAX(`year`) FROM t_year_sales2 WHERE `year` < y.year));
-- 窗口函数
SELECT *
FROM 
(
  SELECT *,MAX(`sale`) OVER(ORDER BY `year` ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS preSale
	FROM t_year_sales2 y
) temp 
WHERE sale = preSale;

1.2 窗口函数与关联子查询

图 商品信息t_product_info 表

需求:按照商品种类查询销售单价高于平均销售单价的商品。

-- 关联子查询
SELECT *,(SELECT AVG(price) FROM t_product_info WHERE `type` = p.type) AS avgPrice
FROM t_product_info p 
WHERE price > (SELECT AVG(price) FROM t_product_info WHERE `type` = p.type);
-- 关联子查询
SELECT *
FROM (
	SELECT *,AVG(price) OVER (PARTITION BY `type`) AS avgPrice
	FROM t_product_info
) temp
WHERE price > avgPrice;

1.3 查询重叠的时间区间

图 酒店预约t_reservation2表

需求:查找出重叠时间的预定

-- 关联子查询
SELECT *
FROM t_reservation2 r 
WHERE EXISTS 
(
	SELECT *
	FROM t_reservation2 r1
	WHERE r1.reserver != r.reserver AND 
	(r.start_date BETWEEN r1.start_date AND r1.end_date
	 OR r.end_date BETWEEN r1.start_date AND r1.end_date	
	 OR (r.start_date <= r1.start_date AND r.end_date >= r1.end_date)
	)
);

这个需求窗口函数较难实现。

1.4 移动平均值

图 银行账户存取款记录t_account表

需求:求当前取款额及最近三次平均取款额(当前行+前两行。当前两行记录不全时,根据既有数据求平均值)。

-- 窗口函数
SELECT *,AVG(amount) OVER (ORDER BY `date` ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS avgAmount
FROM t_account;
-- 关联子查询
SELECT *,(SELECT AVG(amount) FROM t_account WHERE `date` <= a.date LIMIT 3) AS avgAmount
FROM t_account a; 

需求:上面需求改为,当记录少于3行,平均值为NULL。

-- 窗口函数
SELECT *,
CASE WHEN COUNT(*) OVER (ORDER BY `date` ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) < 3 THEN NULL 
ELSE AVG(amount) OVER (ORDER BY `date` ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)  END AS avgAmount
FROM t_account;
-- 关联子查询
SELECT *,
CASE WHEN (SELECT COUNT(*) FROM t_account WHERE `date` <= a.date) < 3 THEN NULL 
ELSE (SELECT AVG(amount) FROM t_account WHERE `date` <= a.date LIMIT 3) END AS avgAmount
FROM t_account a; 

http://www.kler.cn/a/390144.html

相关文章:

  • 随手记:简单实现纯前端文件导出(XLSX)
  • 基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统
  • 矢量拟合(1)Sanathanan–Koerner算法
  • k8s集群安装(kubeadm)
  • Python多进程间通讯(包含共享内存方式)
  • Gurobi学术版+Anaconda安装步骤
  • 什么是C/C++,有什么特点
  • 物联网学习路线来啦!
  • 道可云人工智能元宇宙每日资讯|2024国际虚拟现实创新大会将在青岛举办
  • cache写策略 操作系统
  • nginx 部署2个相同的vue
  • 241111.学习日志——【CSDIY】Cpp零基础速成
  • 2024年11月10日系统架构设计师考试题目回顾
  • 【算法速刷(9/100)】LeetCode —— 42.接雨水
  • 2024年9月青少年软件编程(C语言/C++)等级考试试卷(四级)
  • flask logger 使用 TimedRotatingFileHandler 报错 PermissionError 另一个程序正在使用此文件
  • NVR录像机汇聚管理EasyNVR多品牌NVR管理工具/设备:大华IPC摄像头局域网访问异常解决办法
  • 哪家云服务器好跑AI?瞄准AutoDL(附NVIDIA GPU 算力排名表)
  • Linux基础之病毒编写
  • Docker 操作指令
  • 如何设置el-date-picker的默认截止时间为“23:59:59”
  • 故事121
  • Ceph MDS高可用架构探索:从零到一构建多主一备MDS服务
  • (Go基础)Go的运行流程步骤与包的概念
  • 使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
  • 【Linux系列】 环境配置文件合并的艺术:从`.env`到`.env.combined`