从
SQL Server2012
开始,提供了四个排名分布函数,包括
PERCENT_RANK
、
CUME_DIST
、
PERCENTILE_CONT
和
PERCENTILE_DISC
。其中
PERCENT_RANK
用于计算某行的相对排名,
CUME_DIST
用于计算行的累积分布(即相对位置),
PERCENTILE_CONT
和
PERCENTILE_DISC
用于根据指定的比例返回组中相应的数值,如中位值等。换句话说,
PERCENT_RANK
和
CUME_DIST
是根据数值计算比例,
PERCENTILE_CONT
和
PERCENTILE_DISC
是根据指定的比例计算数值,类似于对
PERCENT_RANK
和
CUME_DIST
的逆运算。
9.4.1 PERCENT_RANK
函数
PERCENT_RANK
用于计算某行的相对排名,返回一个
0
~
1
之间的一个小数值。该函数的
OVER
子句允许有分区和排序子句,并且排序子句是必选项。
下面通过一个示例来说明这种相对排名的计算方法,这里我们仍旧使用
9.1
节创建的
Students
表,下面的语句用于计算学生成绩在自己班级的绝对排名和相对排名,查询结果如表
9-15
所示。
SELECT ClassID, StudentName, Achievement,
RANK() OVER(PARTITION BY ClassID ORDER BY Achievement DESC) AS A_Rank,
PERCENT_RANK() OVER(PARTITION BY ClassID ORDER BY Achievement DESC) ASP_Rank
FROM dbo.Students;
表
9-15
学生成绩在自己班级的绝对排名和相对排名
ClassID
|
StudentName
|
Achievement
|
A_Rank
|
P_Rank
|
1
|
Grace
|
99
|
1
|
0
|
1
|
Andrew
|
99
|
1
|
0
|
1
|
Margaret
|
89
|
3
|
0.666667
|
1
|
Janet
|
75
|
4
|
1
|
2
|
Robert
|
91
|
1
|
0
|
2
|
Steven
|
86
|
2
|
0.5
|
2
|
Michael
|
72
|
3
|
1
|
3
|
Ann
|
94
|
1
|
0
|
3
|
Ken
|
92
|
2
|
0.333333
|
3
|
Ina
|
80
|
3
|
0.666667
|
3
|
Laura
|
75
|
4
|
1
|
对于使用
RANK
函数获得绝对排名,我们在前面已经介绍过。现在看表中的
P_Rank
列的计算方法,公式如下:
(当前行的
RANK
排名
-1
)
/
(分区内总行数
-1
)
从表中可以看出,
Grace
、
Andrew
的
RANK
排名为第
1
,并且当前分区内共有
4
行,所以第一行和第二行的
P_Rank
列值均计算为:
(1-1)/(4-1)=0
。第三行
Margaret
的
P_Rank
列值计算方法为:
(3-1)/(4-1)=0.666667
,表示班级内有
66.667%
的人高于自己的成绩。
9.4.2 CUME_DIST
函数
CUME_DIST
用于计算某个值在一组值内的累积分布,也可以说是该值在一组值中的相对位置。函数返回一个
0
~
1
之间的一个小数值。该函数的
OVER
子句允许有分区和排序子句,并且排序子句是必选项。
下面通过一个示例来说明这种相对位置的计算方法,仍旧使用
9.1
节创建的
Students
表。下面的语句中,
C_Num
列计算的是大于或等于自己学生成绩的人数,
C_Dist
列计算的是大于或等于自己学生成绩的人数占全班人数的比例,查询结果如表
9-16
所示。
SELECT ClassID, StudentName, Achievement,
COUNT(*) OVER(PARTITION BY ClassID ORDER BY Achievement DESC) AS C_Num,
CUME_DIST() OVER(PARTITION BY ClassID ORDER BY Achievement DESC) ASC_Dist
FROM dbo.Students;
表
9-16
计算的是大于或等于自己学生成绩的人数及占全班人数的比例
ClassID
|
StudentName
|
Achievement
|
C_Num
|
C_Dist
|
1
|
Grace
|
99.00
|
2
|
0.5
|
1
|
Andrew
|
99.00
|
2
|
0.5
|
1
|
Margaret
|
89.00
|
3
|
0.75
|
1
|
Janet
|
75.00
|
4
|
1
|
2
|
Robert
|
91.00
|
1
|
0.333333333333333
|
2
|
Steven
|
86.00
|
2
|
0.666666666666667
|
2
|
Michael
|
72.00
|
3
|
1
|
3
|
Ann
|
94.00
|
1
|
0.25
|
3
|
Ken
|
92.00
|
2
|
0.5
|
3
|
Ina
|
80.00
|
3
|
0.75
|
3
|
Laura
|
75.00
|
4
|
1
|
表中
C_Dist
列的计算公司为:
C_Num/
班级总人数
C_Num
是大于或等于自己学生成绩的人数。表中第
1
~
4
行是班级
1
的数据,第一行和第二行
C_Dist
列值的计算方法是:
2/4=0.5
,表示班级中有
50%
的大于或等于自己的成绩。
9.4.3 PERCENTILE_CONT
和
PERCENTILE_DISC
函数
PERCENTILE_CONT
和
PERCENTILE_DISC
用于根据指定的比例返回一组数据中相应位置的值,所指定比例应当是一个
0
~
1
之间的小数。例如,比例为
0.5
(即中位值),这组数字是
1
、
3
、
9
、
12
、
18
,则这个数值应当是
9
。
PERCENTILE_CONT
和
PERCENTILE_DISC
函数的语法格式如下,其中的
WITHIN GROUP
子句用于指定要排序的数值列表,
OVER
子句可以指定一个分区列。
PERCENTILE
函数
(numeric_literal )
WITHINGROUP ( ORDER BY order_by_expression [ ASC | DESC ] )
OVER ( [<partition_by_clause> ] )
下面通过示例来说明这两个函数的使用方法,参考下面的语句。查询结果如表
9-17
所示。
SELECT ClassID, StudentName, Achievement,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BYAchievement DESC)
OVER(PARTITION BYClassID) AS P_Cont,
PERCENTILE_DISC(0.6) WITHIN GROUP (ORDER BYAchievement DESC)
OVER(PARTITION BYClassID) AS P_Disc,
CUME_DIST() OVER(PARTITION BY ClassID
ORDER BY Achievement DESC) AS C_Dist
FROM dbo.Students;
表
9-17
根据指定比例返回相应数值
ClassID
|
StudentName
|
Achievement
|
P_Cont
|
P_Disc
|
C_Dist
|
1
|
Grace
|
99
|
94
|
89
|
0.5
|
1
|
Andrew
|
99
|
94
|
89
|
0.5
|
1
|
Margaret
|
89
|
94
|
89
|
0.75
|
1
|
Janet
|
75
|
94
|
89
|
1
|
2
|
Robert
|
91
|
86
|
86
|
0.333333
|
2
|
Steven
|
86
|
86
|
86
|
0.666667
|
2
|
Michael
|
72
|
86
|
86
|
1
|
3
|
Ann
|
94
|
86
|
80
|
0.25
|
3
|
Ken
|
92
|
86
|
80
|
0.5
|
3
|
Ina
|
80
|
86
|
80
|
0.75
|
3
|
Laura
|
75
|
86
|
80
|
1
|
表中
P_Cont
列计算的是班级中
50%
位置的值,班级
1
共有
4
行,因此
94
是
Achievement
列中第二行和第三行的平均值:
(99+89)/2
。也就是说,对于偶数行,
PERCENTILE_CONT
函数计算的是中间两个数值间的平均值。
而
PERCENTILE_DISC函数不会这样做,它始终返回的是已有值。注意表中的C_Dist列,该列计算的是值得累积分布。当为PERCENTILE_DISC指定一个比例值时,它会查找大于或等于该比例的累积分布值所对应的值。例如,在该示例中我们为函数指定的比例是0.6,在班级1中第一个大于或等于该值的累积分布是0.75,因此该函数返回了89。
Overall_
dis
tribution = spark.
sql
("""
select count(*) as total_,
round(count(case when Completion_rate >= 0 and Completion_rate < 0.25 then 1 end )/count(*),2) as a,
round(count(case when Completion_rate >= 0.25 and.
今天的所有数据:select * from 表名 where DateDiff(dd,datetime类型字段,getdate())=0
昨天的所有数据:select * from 表名 where DateDiff(dd,datetime类型字段,getdate())=1
7天内的所有数据:select * from 表名 where DateDiff(dd,datetime类...
curdate( ) AS date UNION ALL
SELECT
date_sub( curdate( ), INTERVAL 1 DAY ) AS date UNION ALL
SELECT
date_sub( curdate( ), INTERVAL 2 DAY ) AS date UNION ALL
SELECT
date_su
一、场景简介
以下内容是对该问题和经验分享的场景进行简介,可以通过此部分查看此文章内容是否为你可以参考的内容。
使用
SQL
查询实现分区间/分段统计。该
sql
使用常存在于报表的制作,统计数据的
计算
,大屏数据展示等场景。通常我们会面对一类需求,将一组或一批或一张表的数据,根据某一字段按照分段、分区间(有时是自定义区间)的形式,进行汇总统计,
计算
相关数值、占比等。譬如以下场景:
统计某班级(或其他类似团体)某次测试分数
分布
计算
某站点访问量随时间变化的曲线
某地区/某行