您的问题第一部分的答案取决于您使用的 SQL 服务器的版本 - SQL 2005+ 提供了排名功能,这使得这种查询比 SQL 2000 及之前的查询更简单。如果您指出您正在使用哪个平台,我会更详细地更新此内容。
我怀疑处理第 2 部分的最清晰方法是显示最新完整抓取练习的统计数据,否则您不会显示时间一致的排名(尽管,如果您的数据收集练习需要 24 小时,则有一定的自由度已经)。
为了简化这一点,您可以创建一个表来保存有关每个抓取操作的元数据,为每个操作提供一个 id、开始日期和完成日期(至少),并显示与最新完整抓取相关的那些记录。为了使这更容易,您可以从数据收集表中删除“抓取日期”,并将其替换为将每个数据行链接到抓取表中的一行的外键。
编辑
以下代码说明了如何按用户的最新分数对用户进行排名,无论它们是否时间一致:
create table #scrape
(userName varchar(20)
,wins int
,losses int
,scrapeDate datetime
)
INSERT #scrape
select 'Alice',100,200,'20090101'
union select 'Alice',120,210,'20090201'
union select 'Bob' ,200,200,'20090101'
union select 'Clara',300,100,'20090101'
union select 'Clara',300,210,'20090201'
union select 'Dave' ,100,10 ,'20090101'
;with latestScrapeCTE
AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY userName
ORDER BY scrapeDate desc
) AS rn
,wins + losses AS totalPlayed
,wins - losses as winDiff
from #scrape
)
SELECT userName
,wins
,losses
,scrapeDate
,winDiff
,totalPlayed
,RANK() OVER (ORDER BY winDiff desc
,totalPlayed desc
) as rankPos
FROM latestScrapeCTE
WHERE rn = 1
ORDER BY rankPos
编辑 2
使用元数据表选择最新完整抓取的示例:
create table #scrape_run
(runID int identity
,startDate datetime
,completedDate datetime
)
create table #scrape
(userName varchar(20)
,wins int
,losses int
,scrapeRunID int
)
INSERT #scrape_run
select '20090101', '20090102'
union select '20090201', null --null completion date indicates that the scrape is not complete
INSERT #scrape
select 'Alice',100,200,1
union select 'Alice',120,210,2
union select 'Bob' ,200,200,1
union select 'Clara',300,100,1
union select 'Clara',300,210,2
union select 'Dave' ,100,10 ,1
;with latestScrapeCTE
AS
(
SELECT TOP 1 runID
,startDate
FROM #scrape_run
WHERE completedDate IS NOT NULL
)
SELECT userName
,wins
,losses
,startDate AS scrapeDate
,wins - losses AS winDiff
,wins + losses AS totalPlayed
,RANK() OVER (ORDER BY (wins - losses) desc
,(wins + losses) desc
) as rankPos
FROM #scrape
JOIN latestScrapeCTE
ON runID = scrapeRunID
ORDER BY rankPos