惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
S
SegmentFault 最新的问题
V
Visual Studio Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
美团技术团队
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
有赞技术团队
有赞技术团队
量子位
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
博客园 - 叶小钗
月光博客
月光博客
P
Proofpoint News Feed
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
Stack Overflow Blog
Stack Overflow Blog

博客园 - herry507

在将 nvarchar 值 '0.00000' 转换成数据类型 int 时失败。 excel VBA点击图片放大缩小 mssql 解析XML 特殊字符造成浏览器显示异常 asysc /wait task 示例执行 MSSQL中解析JSON特殊字符 直接执行与EXCU里执行,竟效果不同 占有率最高的工业总线:PROFINET、Modbus 与 EtherCAT nvarchar和varchar区别 Wappalyzer的分析和欺骗 mssql 中group by cube,rollup,grouping示例 深入理解 Calculate 函数 android手机文件夹目录结构 手机文件管理目录 如何在Android中获取图片路径 线程间操作无效: 从不是创建控件“******”的线程访问它。 Android 整理常用的第三方库 androids上报表开发 为什么要用模块化、组件化才能完成 Android 项目中类加载功能? android多模块 安卓模块是什么意思 如何使用Android访问文件系统路径 让Android Studo 不编译某个Java文件 Java中list不包含某个元素 java list所在包 转载 解决AS插件与Gradle版本之间的对应问题
开窗函数进阶last_value特别地方
herry507 · 2024-03-22 · via 博客园 - herry507

有了开窗函数,让我们做统计方便很多。
row_number(),sum,等常规用法,便不在这里讲。

我们从一个问题开始

with abc as ( select 1 as id union all select 2 union all select 3 union all select 4 ) select id, FIRST_VALUE(id) over(order by id ) as firstid, LAST_VALUE(id) over(order by id) as lastid from abc

看结果 明显第二列我的原意是想取得最后一行的值。即为4

185130486dcdf8e56cc70e5a.webp

FIRST_VALUE 一看就明白了。但last_value 为什么就是当前行的值呢?明明该是4才对啊。

原因在于这两个函数 可以用rows 指定作用域。 而默认的作用域是
RANGE UNBOUNDED PRECEDING AND CURRENT ROW
就是说从窗口的第一行到当前行。 所以last_value 最后一行肯定是当前行了。

知道原因后,只需要改掉行的作用域就可以了。

with abc as ( select 1 as id union all select 2 union all select 3 uno union all select 4 ) select id, FIRST_VALUE(id) over(order by id ) as firstid, LAST_VALUE(id) over(order by id rows between UNBOUNDED PRECEDING AND UNBOUNDED following ) as lastid from abc

185130487ea84aeeae74701d.webp

rows 子句的一些关键字
UNBOUNDED PRECEDING 窗口函数第一行
UNBOUNDED following 窗口函数最后一行
CURRENT ROW 当前行

n PRECEDING 当前行的前几行

所以用开窗函数,一定要注意行的作用域

我们再继续作用域

那窗口函数的行作用域到底哪些呢?

排名函数
rank、ntile、dense_rank、row_number 行的作用域都是全结果集,且不支持指定 rows_range_clause

聚合函数
count、sum,count,max,min等 都支持指定rows_range_clause 但如果不指定order by 则是全表,指定了order by 则行范围默认就是 RANGE UNBOUNDED PRECEDING AND CURRENT ROW

;with abc as ( select 0 as id union all select 1 union all select 2 union all select 3 ) select id, sum(id) over(), count(id)over(), sum(id) over(order by id), count(id)over(order by id), sum(id) over(order by id rows between UNBOUNDED PRECEDING AND UNBOUNDED following ), count(id)over(order by id rows between UNBOUNDED PRECEDING AND UNBOUNDED following ) from abc

分析函数
lag,lead 都不支持 指定rows_range_clause

LAST_VALUE 、FIRST_VALUE 默认就是 RANGE UNBOUNDED PRECEDING AND CURRENT ROW

最后我们再分析一下 rows与range的区别

下面的显示代码为 SQL Server的

declare @t table(ord int,billdate varchar(10),add_value int,dec_value int,end_value int) insert into @t select 1,'期初',0,0,100 union all select 2,'2021-01-01',100,0,0 union all select 3,'2021-01-02',0,100,0 union all select 4,'2021-01-03',0,100,0 union all select 5,'2021-01-04',100,0,0 union all select 5,'2021-01-04',100,0,0 select *,sum(add_value -dec_value + end_value ) over(order by ord) as new_end from @t a

end_value 这个字段要实现流水账的功能,即 end_value = 第一行期初行 end_value + add_value - decvalue

执行结果如图

44.webp

可以看到第5行 NEW_END该为100 而不是200

上面说过。 order by 没有显示给出行的作用域范围。则默认为
RANGE between UNBOUNDED PRECEDING AND CURRENT ROW

我改为显示指定 并且用ROWS关键字

declare @t table(ord int,billdate varchar(10),add_value int,dec_value int,end_value int) insert into @t select 1,'期初',0,0,100 union all select 2,'2021-01-01',100,0,0 union all select 3,'2021-01-02',0,100,0 union all select 4,'2021-01-03',0,100,0 union all select 5,'2021-01-04',100,0,0 union all select 5,'2021-01-04',100,0,0 select *,sum(add_value -dec_value + end_value ) over(order by ord rows between UNBOUNDED PRECEDING AND CURRENT ROW) as new_end from @t a

555.webp
可以看到第5行 new_end结果是我期望的100了。

两个例子可以看出 range 关键字,是以 order by 字段的值 做为基准的。因为最后两行的ord 都 = 5 所以就认为是一样的。

而rows 是行号为基准的。
这就是 rows 与 range的区别

n following 当前行的后几行

转自https://www.modb.pro/db/112099?utm_source=index_ai