1.首先先简单描述一下SQL server的存储过程,通俗的说,就是将一个或多个Transact-SQL语句分组到逻辑单元中,并作为对象存储在数据库服务器中。 当第一次调用存储过程时,SQL Server会创建执行计划并将其存储在计划缓存中。 在之后的存储过程执行中,SQL Server重用该程序,以便存储过程可以非常快速地执行并具有可靠的性能.
下面是几种简单的窗口函数
1.cume_dist() 计算一组值中值的累积分布
场景:生成一个报表,其中包含数据集中的顶部或底部有x%值,如销售人员占销售额的
前5%
语法:PARTITION BY 子句将行分配到应用了CUME_DIST的多个分区,如果省略PARTITION BY子句,函数会将整个结果集视为单个分区;ORDER BY 子句将NULL值视为最低值;函数的求值结果大于0且小于或等于1.
练习:
select
CONCAT_WS(' ',first_name,last_name) full_name,net_sales,
CUME_DIST() over (
order by net_sales desc) cume_dist
from sales s
inner join staffs m
on m.id=s.id
where YEAR =2021
with cte_sales AS(
SELECT
CONCAT_WS(' ',first_name,last_name) full_name,net_sales,YEAR,
CUME_DIST() over (
partition by year
order by net_sales desc
) cume_dist
from sales s
inner join staffs m
on m.id=s.id
where YEAR in (2020,2021)
)
select *
from cte_sales
where cume_dist >0.20
2.dense_rank函数,为结果集的分区中的每一行分配一个排名
不同:与rank函数相比,这个函数返回连续的排名值,如果分区中的行具有相同的值,将获得相同的排名
练习:
select cno,
DENSE_RANK() over(
order by cno
) my_dense_rank
from dbo.Courses
select cno,
RANK() over(
order by cno
)my_rank
from dbo.Courses
select id,name,price,
DENSE_RANK() over(
order by price desc
)price_rank
from products
3.first_value函数,为了获取结果集的有序分区中的第一个值
语法:partition by 子句按年分配行分为两个分区
order by 子句按数量从低到高对每个分区中的行进行排序
first_value()函数分别应用于每个分区
练习:
--单个分区
select name,year,qty,
FIRST_VALUE(name) over(
order by qty
)lowest
from dbo.sales
where YEAR=2021
--两个分区
select name,year,qty,
FIRST_VALUE(name)over(
partition by year
order by qty
)lowest
from dbo.sales
where YEAR between 2016 and 2017
4.last_value()函数,为了返回结果集的有序分区中的最后一个值
语法:partition by 子句按年分配行分为两个分区
order by 子句按数量从低到高对每个分区中的行进行排序
last_value()函数分别应用于每个分区
UNBOUNDED PRECEDING和UNBOUNDED FOLLOWING子句之间的范围定义了从第一行开始到最后一行结束的分区中的帧.
练习:
select name,year,qty,
LAST_VALUE(name)over(
order by qty
range between unbounded preceding and unbounded following
)highest
from dbo.sales
where year =2016;
select name,year,qty,
LAST_VALUE(name) over(
partition by year
order by qty
range between unbounded preceding and unbounded following
)highest
from dbo.sales
where year in (2016,2017);
5.percent_rank函数计算结果集的分区中值的相对位置
语法:partition by 子句将行分配到percent_rank函数的多个分区
order by子句指定每个分区中行的逻辑顺序,由于percent_rank()对顺序敏感,因此需要order by
percent_rank()的结果大于0且小于或等于1
练习:
select
CONCAT_WS(' ',first_name,last_name) full_name,sales,
PERCENT_RANK() over(
order by sales desc
)precent_rank
from net_sales n
inner join staffs m
on m.id=n.id
where year=2016
下面是sql server常用的查询语句
1.offset fetch子句来限制查询返回的行数
语法:offset子句指定在开始从查询返回行之前要跳过的行数,可以是大于或等于零的常量,变量或参数。
fetch子句指定在处理offset子句后要返回的行数,可以是大于或等于1的常量,变量或标量。
offset子句是必需的,而fetch子句是可选的
注意:必须将offset和fetch子句与order by子句一起使用,否则会报错。offset和fetch子句比实现top子句更适合实现查询分页的方案。
练习:select * from dbo.Students
--跳过前2个学生并返回其余学生
select sno,sname,age
from dbo.Students
order by SNO,SNAME,AGE
offset 2 rows
--跳过前2个学生并选择接下来的3个学生
select sno,sname,age
from dbo.Students
order by SNO,SNAME,AGE
offset 2 rows
fetch next 3 rows only;
--获得前2个学号在前的学生
select sno,sname,age
from dbo.Students
order by SNO desc,SNAME,AGE
offset 0 rows
fetch first 2 rows only