【sql】- Sql Server 中的窗口(分析)函数实现类似游标访问效果

前言

     小编在写存储过程中遇到了几个函数,貌似不是很熟,把它记录下来和大家一起学习。

正文

分析函数概念

     SQL Server函数分为很多种,常见的有字符串函数、数学函数、时间日期函数、类型转换函数(前几篇博客中提到)、聚合函数、系统函数等,现在来看一下分析函数,也叫窗口函数。
     分析函数是SQL Server2012 开发新特性,分析函数(或称解析函数)基于一组行计算聚合值。不过,与聚合函数不同,它们可能针对每个组返回多行。可以使用分析函数来计算移动平均线、运行总计、百分比或一个组内的前 N 个结果。

分析函数种类

这里写图片描述

介绍几个常用的分析函数

1、First_Value ()

    First_Value返回结果集中某列第一条数据的值,跟TOP 1效果一样
语法

FIRST_VALUE ( [scalar_expression ] )   
    OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )

partition_by_clause --  FROM 子句生成的结果集划分为要应用函数的分区。 如果未指定,则此函数将查询结果集的所有行视为单个组。
order_by_clause  -- 确定执行操作的逻辑顺序。
order_by_clause  -- rows_range_clause 通过指定起点和终点,限制分区中的行数。   

示例

-- 查询同一工单下的第一个工序(根据PK升序)
-- 按照PK 升序排列的第一行 StepQueue
SELECT StepQueue ,FIRST_VALUE(StepQueue) OVER (ORDER BY PK ) AS newStepQueue FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03' 

这里写图片描述

2、Last_Value()

    Last_Value返回结果集中某列最后一条数据的值
语法

LAST_VALUE ( [scalar_expression )   
    OVER ( [ partition_by_clause ] order_by_clause rows_range_clause )   

示例

-- 查询同一工单下的最后一个工序(根据PK升序)
SELECT StepQueue ,LAST_VALUE(StepQueue) OVER (ORDER BY PK ) AS LastStepQueue FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03' 

这里写图片描述

    看到这里,或许您就该提问了:为什么不是110 ? 值都不一样?
    其实,Last _Value函数 取得是按pk升序排列的相同pk最后一行stepQueue,可以再用一个例子来验证:

-- 查询同一工单下的最后一个工序(根据BOPID升序)
-- 按BOPID升序排列的相同BOPID最后一行stepQueue
SELECT BOPID,StepQueue ,LAST_VALUE(StepQueue) OVER (ORDER BY BOPID ) AS LastStepQueue FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03' 

这里写图片描述
    再来看 First_Value函数 是不是预期结果呢?

SELECT BOPID,StepQueue ,FIRST_VALUE(StepQueue) OVER (ORDER BY BOPID) AS newStepQueue FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03' 

这里写图片描述
    不是 预期效果 ,当加入了分组函数之后才会得到预期效果

SELECT BOPID,StepQueue ,FIRST_VALUE(StepQueue) OVER (PARTITION BY BOPID ORDER BY BOPID) AS newStepQueue FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03'  

这里写图片描述

    注意: 分析函数分析的时候是在一个分析窗口中进行的,默认的窗口是当前组的第一行到当前行,查询结果是会受Order By语句影响的。
问题 :本例中的First_Value()和Last_Value()函数是不一样的,请教各位大神 为什么会这样,小编还需要再理解 ~~

3、LAG()

    访问相同结果集中先前行的数据,而用不使用 SQL Server 2016 中的自联接。 LAG 以当前行之前的给定物理偏移量来提供对行的访问。
    在 SELECT 语句中使用此分析函数可将当前行中的值与先前行中的值进行比较。
语法

LAG (scalar_expression [,offset] [,default])  
    OVER ( [ partition_by_clause ] order_by_clause )  
scalar_expression  -- 要返回的值
offset  -- 当前行(从中获得取值)后的行数,默认为1,不能为负值
over -- 确定窗口的范围
partition by -- 分区
order by -- 排序

示例


---向前查找   199 为默认值(null →199)
SELECT StepQueue, LAG(StepQueue,1,199) OVER (ORDER BY PK) AS preStep  FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03'  ORDER BY BOPID,PK

这里写图片描述

4、LEAD()

    访问相同结果集的后续行中的数据,而不使用 SQL Server 2012 中的自联接。 LEAD 以当前行之后的给定物理偏移量来提供对行的访问。
    在 SELECT 语句中使用此分析函数可将当前行中的值与后续行中的值进行比较。
语法

LEAD ( scalar_expression [ ,offset ] , [ default ] )     OVER ( [ partition_by_clause ] order_by_clause )

示例

---向后查找   100 为默认值(null →100)
SELECT StepQueue, LEAD(StepQueue,2,100) OVER (ORDER BY PK)AS nextStep  FROM dbo.PLM_BOP_PPR WHERE OrderID = '100000003921-03'  ORDER BY BOPID,PK

这里写图片描述

总结

    小编有些不解的是First_Value() 和Last_Value() 语法一样,使用起来就不是预期的效果,期待路过的你在评论区留言~~
    First_Value()函数实现结果集中第一条记录的访问,Last_Value()函数实现结果集中最后一条记录的访问,Lag()函数实现结果集中前些行的访问,Lead ()函数实现结果集中后续行的访问,是不是有种游标访问的效果?感谢您的阅读,期待下次再会~~

猜你喜欢

转载自blog.csdn.net/zt15732625878/article/details/79825558