总结SQL Server窗口函数的简单使用
总结SQL Server窗口函数的简单使用
前言:我一直十分喜欢使用SQL Server2005/2008的窗口函数,排名函数ROW_NUMBER()尤甚。今天晚上我在查看SQL Server开发的相关文档,整理收藏夹发现了两篇收藏已久的好文,后知后觉,读后又有点收获,顺便再总结一下。
一、从一个熟悉的示例说起
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
WITH Record AS ( SELECT Row_Number() OVER ( ORDER BY Id DESC ) AS RecordNumber, Id, FirstName, LastName, Height, Weight FROM Person (NOLOCK) ) SELECT RecordNumber, ( SELECT COUNT (0) FROM Record) AS TotalCount, Id, FirstName, LastName, Height, Weight FROM Record WHERE RecordNumber BETWEEN 1 AND 10 |
二、窗口函数
1
2
3
4
5
6
7
8
|
CREATE TABLE [StudentScore]( [Id] [ int ] IDENTITY(1,1) NOT NULL , [StudentId] [ int ] NOT NULL CONSTRAINT [DF_StudentScore_StudentId] DEFAULT ((0)), [ClassId] [ int ] NOT NULL CONSTRAINT [DF_StudentScore_ClassId] DEFAULT ((0)), [CourseId] [ int ] NOT NULL CONSTRAINT [DF_StudentScore_CourseId] DEFAULT ((0)), [Score] [ float ] NOT NULL CONSTRAINT [DF_StudentScore_Score] DEFAULT ((0)), [CreateDate] [datetime] NOT NULL CONSTRAINT [DF_StudentScore_CreateDate] DEFAULT (getdate()) ) ON [ PRIMARY ] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
--CourseId 2:语文 4:数学 8:英语 --1班学生成绩 INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,1,2,85) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,1,2,95.5) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,1,2,90) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,1,4,90) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,1,4,98) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,1,4,89) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,1,8,80) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,1,8,75.5) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,1,8,77) --2班学生成绩 INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,2,2,90) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,2,2,77) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,2,2,78) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (4,2,2,83) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,2,4,98) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,2,4,95) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,2,4,78) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (4,2,4,100) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,2,8,85) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,2,8,90) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,2,8,86) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (4,2,8,78.5) --3班学生成绩 INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,3,2,82) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,3,2,78) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,3,2,91) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,3,4,83) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,3,4,78) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,3,4,99) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (1,3,8,86) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (2,3,8,78) INSERT INTO StudentScore(StudentId,ClassId,CourseId,Score) VALUES (3,3,8,97) |
窗口函数使用OVER函数实现,OVER函数分带参和不带参两种。其中可选参数PARTITION BY用于将数据按照特定字段分组。
1
2
3
4
5
6
7
8
9
10
11
|
SELECT --Id, --CreateDate, StudentId, ClassId, CourseId, Score, CAST ( AVG (Score) OVER() AS decimal (5,2) ) AS '语文平均分' FROM StudentScore WHERE CourseId=2 |
1
2
3
4
5
6
7
8
9
10
11
|
SELECT Id, CreateDate, StudentId, ClassId, CourseId, Score, CAST ( AVG (Score) OVER(PARTITION BY ClassId ) AS decimal (5,2) ) AS '语文平均分' FROM StudentScore WHERE CourseId=2 |
b、可以在表达式中混合使用基本列和聚合列
二、让人爱不释手的排名函数
1
2
3
4
5
6
7
8
9
10
11
|
SELECT Id, -- CreateDate, ROW_NUMBER() OVER( ORDER BY Score DESC ) AS '序号' , StudentId, ClassId, CourseId, Score FROM StudentScore WHERE CourseId=8 |
1
2
3
4
5
6
7
8
9
10
11
|
SELECT Id, -- CreateDate, RANK() OVER( ORDER BY Score DESC ) AS '序号' , StudentId, ClassId, CourseId, Score FROM StudentScore WHERE CourseId=8 |
b、不同的是,ROW_NUMBER函数为每一个值生成唯一的序号,而RANK函数为相同的值生成相同的序号。
上图中,两个86分的学生对应的序号都是3,而接着排在它们下面的序号直接变成了5。
1
2
3
4
5
6
7
8
9
10
11
|
SELECT Id, -- CreateDate, DENSE_RANK() OVER( ORDER BY Score DESC ) AS '序号' , StudentId, ClassId, CourseId, Score FROM StudentScore WHERE CourseId=8 |
如果分区的行数不能被 integer_expression 整除,则将导致一个成员有两种大小不同的组。按照 OVER 子句指定的顺序,较大的组排在较小的组前面。
1
2
3
4
5
6
7
8
9
10
11
|
SELECT Id, -- CreateDate, NTILE(6) OVER( ORDER BY ClassId DESC ) AS '组编号' , StudentId, ClassId, CourseId, Score FROM StudentScore WHERE CourseId=8 |
总结SQL Server窗口函数的简单使用的更多相关文章
- SQL Server授权购买简单介绍
SQL Server授权购买简单介绍 之前有同事问我,使用盗版序列号的SQL Server到底有没有性能限制,之前本人一直没有深入研究过,后来经过一番资料搜集和查证,汇总成这篇文章 微软的SQL Se ...
- (4.34)sql server窗口函数
关键词:sql server窗口函数,窗口函数,分析函数 如果分析函数不可用,那么可能是版本还不支持 Window Function 包含了 4 个大类.分别是: 1 - Rank Function ...
- SQL Server Profiler的简单使用
SQL Server Profiler可以检测在数据上执行的语句,特别是有的项目不直接使用sql语句,直接使用ORM框架的系统处理数据库的项目,在调试sql语句时,给了很大的帮助. 之前写了使用SQL ...
- SQL Server Service Broker 简单例子 (转)
SQL Server Service Broker服务体系结构 消息类型 — 定义应用程序间交换的消息的名称.还可以选择是否验证消息.约定 — 指定给定会话中的消息方向和消息类型.队列 — 存储消息. ...
- SQL Server Profiler的简单使用(监控mssql)
SQL Server Profiler可以检测在数据上执行的语句,特别是有的项目不直接使用sql语句,直接使用ORM框架的系统处理数据库的项目,在调试sql语句时,给了很大的帮助. 之前写了使用SQL ...
- mySql学习笔记:比sql server书写要简单
在学mySql.总的感觉,mySql与Sql Server差不多,语法都很象,但mySql也许是吸取了SQL SERVER的一些经验,SQL语句书写起来更加简单. 比如说,设置主键.索引,SQL SE ...
- SQL Server窗口函数:ROWS与RANGE
几乎每次我展示SQL Server里的窗口时,人们都非常有兴趣知道,当你定义你的窗口(指定的一组行)时,ROWS与RANGE选项之间的区别.因此在今天的文章里我想给你展示下这些选项的区别,对于你的分析 ...
- C#对于sql server数据库的简单操作
1.在用windows模式登陆sql server 数据库 简历一个student的数据库,然后新建查询: create table student ( id int auto_increment p ...
- SQL SERVER数据库的简单介绍
一.数据库技术的发展 数据库技术是应数据管理任务的需求而产生的,先后经历了人工管理.文件系统.数据库系统等三个阶段. 二.关系型数据库 SQL Server属于关系型数据库. 关系模型 以二维表来描述 ...
随机推荐
- Paint Tree
题意: 给定一棵n个点的树,给定平面上n个点,将n个点用线段连起来画成树的形状,使得不存在不在端点相交的线段,构造出一种情况. 解法: 首先观察我们常规画出来的树形图可知,树的子树是根据极角分开的,这 ...
- HDOj-1425
sort Time Limit: 6000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 微信小程序开发之三元运算符代替wx.if/wx.else
直接上代码 实现功能为:当fbphotoFirst为空时,src路径为“pic/信息反馈1-1_14.png“,并且点击事件uploadfbphotoFirst有效,否则为路径fbphotoFirst ...
- RXSwift01
//创建 Observable 序列 func createObservable(){ /* let observable = Observable<Int>.just(5) let ob ...
- Codeforces Round #269 (Div. 2) A,B,C,D
CodeForces - 471A 首先要有四个数相等,然后剩下两个数不同就是Bear,否则就是Elephant. #include <bits/stdc++.h> using names ...
- POJ3268【最短路】
题意: n个点m条有向边,每个点有一头牛,每头牛会沿着各自的最短路先到x点,然后又从x点到各自的点,求这些牛中间最短路程最大的牛. 思路: 从x点到各点的最短路不用说了,裸的最短路: 但是从所有点到x ...
- Lightoj1028 【数学-乘法原理】
题意: 给你一个数,问你有多少种进制对n的表示,存在后导零: 比如30:用3进制表示: 1010 思路: 我们发现,就是一个数的约数就能对n表示最后存在后导零: 计算[2 ,n]之间的n的约数个数. ...
- 如何快速将vc++的类转换为c#/cli
所有需要的工具: 1. TextTemplate 2. P/Invoke Interop Assistant 3. DotNetResolver vc++的native类一般是无法直接暴露在.net环 ...
- 【BZOJ1174】: [Balkan2007]Toponyms
→原题← ↑这样子我就不复制题面啦~ 就是一题很裸的字典树而已,不过空间卡的很死,直接开个数组 tr[N][52] 什么之类的一定会RE的(惨痛的教训) 当字典树空间不够而时间限制又比较宽松时,我们可 ...
- log4j.xml中Filter的用法
前言 log4j中常用的Filter分为四种:DenyAllFilter.LevelMatchFilter.LevelRangeFilter.StringMatchFilter. 当appender匹 ...