我怎样才能查询排名在我的数据库的用户,但只考虑每个用户的最近一次入境?(How can I quer

2019-07-17 10:58发布

可以说我有所谓的“刮”可能设置像一个数据库表:

UserID (int)   
UserName (varchar)  
Wins (int)   
Losses (int)  
ScrapeDate (datetime)

我想能够根据他们的胜利/损失比率排名我的用户。 然而,每个星期我会刮在用户新的数据,使在刮表中的另一个项目。

我如何可以查询由胜/负排序的用户列表,但只有考虑到最近的条目(ScrapeDate)?

另外,你认为它很重要,人们会被击中的部位和刮可能是在完成中间?

例如,我可以有:

1 - Bob - Wins: 320 - Losses: 110 - ScrapeDate: 7/8/09  
1 - Bob - Wins: 360 - Losses: 122 - ScrapeDate: 7/17/09  
2 - Frank - Wins: 115 - Losses: 20 - ScrapeDate: 7/8/09  

其中,这表示只更新鲍勃至今一刮,并在更新弗兰克的过程,但还没有被插入。 你将如何处理这种情况呢?

所以,我的问题是:

  1. 你会如何处理只查询每个用户的最近凑来确定排名
  2. 你认为的事实,数据库可能是在更新(尤其是如果刮擦可能需要1天才能完成)的状态,而不是所有的用户已经完全更新还重要吗? 如果是的话,你会如何处理呢?

谢谢大家,谢谢你们,感谢你们给予我对我相关的问题您的回答:

当从网页刮了大量的统计资料,我应该多久插入我的数据库中收集的结果?

Answer 1:

这就是我所说的“最伟大的正每个组”的问题。 它配备了每周几次在计算器上。

我使用一个外部联接的技术来解决这类问题:

SELECT s1.*, s1.wins / s1.losses AS win_loss_ratio
FROM Scrape s1
LEFT OUTER JOIN Scrape s2
  ON (s1.username = s2.username AND s1.ScrapeDate < s2.ScrapeDate)
WHERE s2.username IS NULL
ORDER BY win_loss_ratio DESC;

这将返回每个用户名只有一排-与最值的行ScrapeDate列。 这就是外连接什么是,要尽量配合s1与另一列s2具有相同的用户名和更大的日期。 如果没有这样的行,外部连接返回NULL对于所有列s2 ,然后我们知道s1对应于与该给定用户名的最大日起一行。

当你有一个进展中的部分完成的刮这也应该工作。

这种技术并不一定如CTE和排名的解决方案其他答案已经给出快捷。 你应该尝试,看看有什么适合你更好。 我喜欢我的解决方案的原因是,它工作在SQL中的任何味道。



Answer 2:

尝试是这样的:

  1. 选择用户名并为每个用户最后一个条目的最大日期。
  2. 选择和订购的记录,我们将根据上面的查询结果中的排名。

这应该工作,但是取决于你的数据库的大小。

DECLARE 
    @last_entries TABLE(id int, dte datetime)

-- insert date (dte) of last entry for each user (id)
INSERT INTO
    @last_entries (id, dte)
SELECT
    UserID,
    MAX(ScrapeDate)
FROM
    Scrape WITH (NOLOCK)
GROUP BY
    UserID

-- select ranking
SELECT
    -- optionally you can use RANK OVER() function to get rank value
    UserName,
    Wins,
    Losses
FROM
    @last_entries
    JOIN
        Scraps WITH (NOLOCK)
    ON
        UserID = id
        AND ScrapeDate = dte
ORDER BY
    Winds,
    Losses

我没有测试此代码,因此它无法在第一次运行时编译。



Answer 3:

回答你的问题的第一部分取决于你使用的是SQL Server版本- 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


文章来源: How can I query rankings for the users in my DB, but only consider the latest entry for each user?