排名趋势公式
Posted The blog of Andy Wei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排名趋势公式相关的知识,希望对你有一定的参考价值。
开始
这里有个连续几个月的个人销售数据,如:
图1.
要求对个人销量按月进行排名,还能够描述出一个人在连续几个月的排名趋势,是上升还是下降,连续上升多少个月,连续下降多少个月,如图2.
图2.
分析
由于要描述连续升和连续降的特点,每月的连续升降,需要参考本月之前的排名情况,所以最好是通过实体表来存储每月的排名数据。如图3.
图3.
在 图3,中,有一个字段RankTrend描述排名趋势,正数(+n)表示上升,负数(-n)表示下降,0表示第一次排名或名次不变。
场景1:第一次排名从0开始计数,下个月名次上升的情况,RankTrend +=1, 反之,名次出现下降 ,RankTrend -=1 。
图4.
Kent 在1月份第一次加入排名,1月排名趋势为0;2月份,名次从第4名升到第2名,属于上升趋势,那么RankTrend +=1; 3月也是一样,从2月的第2名升到第1名,那么RankTrend +=1;
图5.
John 在1月份第一次加入排名,1月排名趋势为0;2月份,名次从第1名降到第5名,属于下降趋势,那么RankTrend -=1; 3月也是一样,从2月的第5名降到第6名,那么RankTrend -=1;
场景2:上个月的排名趋势是上升的,即RankTrend = (+n), 本月排名突然下降,那么RankTrend = (-1),这里不能直接RankTrend -=1,因为直接减1不能体现连续升降趋势。
图6.
分析方法如前面(略.)
场景3:上个月的排名趋势是下降的,即RankTrend = (-n), 本月排名突然下降,那么RankTrend = (+1),这里不能直接RankTrend +=1,因为直接加1不能体现连续升降趋势。
图7.
分析方法如前面(略.)
排名趋势公式
根据前面的分析,我们涉及到一些数值,(+n),(-n) ,-1 , 1 , 0 。结合这些数,我们可以通过一个简单的数字组合和位运算,整理得出一个排名趋势公式:
【排名趋势】 = isnull( sign( [上月名次] - [本月名次] ) + [上月排名趋势值] x ( 1 - abs(sign( sign([上月名次] - [本月名次]) XOR sign([上月排名趋势值]) )) ) ,0)
[注明]:
- isnull()函数是判断Null的时候取0
- sign() 函数是正负函数,返回-1,0,1
- abs() 函数是取绝对值
- XOR 表示异或运算
具体可以自己去拆分,这里暂时不详解。
测试例子
1.建表和Insert 测试数据
use tempdb go if object_id(\'PersonalSalesRank\') Is not null drop Table PersonalSalesRank go create table PersonalSalesRank(Name nvarchar(20),YM date, SalesQty int ,RankNr int,RankTrend int) go set nocount on insert into dbo.PersonalSalesRank ( Name , YM , SalesQty ) values --2017-01 (\'Kent\',\'20170101\',400), (\'John\',\'20170101\',758), (\'Rob\',\'20170101\',365), (\'Ruben\',\'20170101\',487), (\'Andy\',\'20170101\',651), --2017-02 (\'Andy\',\'20170201\',668), (\'Christy\',\'20170201\',541), (\'Kent\',\'20170201\',712), (\'Ruben\',\'20170201\',729), (\'Rob\',\'20170201\',365), (\'John\',\'20170201\',465), --2017-03 (\'Andy\',\'20170301\',651), (\'Christy\',\'20170301\',588), (\'Kent\',\'20170301\',769), (\'Ruben\',\'20170301\',752), (\'Rob\',\'20170301\',552), (\'John\',\'20170301\',421) go
2.创建排名趋势函数
if object_id(\'fn_RankTrend\') Is not null drop function fn_RankTrend go /******************************************************************************************** %% Program Name :fn_RankTrend %% Author : Andy.Wei %% Description : %% InParameter : %% OutParameter : %% Created Date : 2017-05-12 %% Revision History : %% Modified Date Modified By version Description %% ********************************************************************************************/ create function fn_RankTrend ( @CurrentRankNr int, @LastRankNr int, @LastRankTrend int ) returns int as begin return(isnull(sign( @LastRankNr - @CurrentRankNr) + @LastRankTrend * ( 1 - abs(sign( sign(@LastRankNr - @CurrentRankNr)^sign(@LastRankTrend) )) ) ,0)) end go
3. 计算排名
--排名 ;with cte_Rank as ( select RankNr,dense_rank() over(partition by YM order by SalesQty desc) as RankNr_1 from dbo.PersonalSalesRank ) update a set a.RankNr=a.RankNr_1 from cte_Rank a
4. 计算排名趋势
--更新排名趋势 declare @YM date=\'20170101\' while(1=1) begin update a set a.RankTrend=dbo.fn_RankTrend(a.RankNr,b.RankNr,b.RankTrend) from dbo.PersonalSalesRank a left join dbo.PersonalSalesRank b on b.Name=a.Name and b.YM=dateadd(month,-1,@YM) where a.YM=@YM; if @@ROWCOUNT =0 break; print @YM set @YM=dateadd(month,1,@YM) end
5. 测试
select name as [姓名], convert(char(7),a.YM,121) as [月份], a.SalesQty as [销量], convert(nvarchar(20),N\'第 \'+rtrim(a.RankNr)+N\' 名\') as [排名], case sign(a.RankTrend) when -1 then N\'↓\' when 1 then N\'↑\' else N\'\' end as [排名升降], case when a.RankTrend>=2 then N\'连续\'+rtrim(abs(a.RankTrend))+N\'月\' else N\'\' end as [连续上升], case when a.RankTrend<=-2 then N\'连续\'+rtrim(abs(a.RankTrend))+N\'月\' else N\'\' end as [连续下降] from dbo.PersonalSalesRank a order by 2,3 desc go
最后
这只是一个简单的例子,但可以从简单的例子发现一些事物的某种共性,由此可以明白它可以应用于相识而不同的各种应用案例中。
以上是关于排名趋势公式的主要内容,如果未能解决你的问题,请参考以下文章
PHP 搜索引擎排名跟踪器 - RankTrackr访问片段
2018数据分析数据科学以及机器学习领域顶级工具的排名与趋势
DB-Engines 2017年3月数据库排名发布,呈大面积掉分趋势