Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 我如何查询我的数据库中的用户排名,而只考虑每个用户的最新条目?_Sql_Database_Sql Server 2005_Screen Scraping_Greatest N Per Group - Fatal编程技术网

Sql 我如何查询我的数据库中的用户排名,而只考虑每个用户的最新条目?

Sql 我如何查询我的数据库中的用户排名,而只考虑每个用户的最新条目?,sql,database,sql-server-2005,screen-scraping,greatest-n-per-group,Sql,Database,Sql Server 2005,Screen Scraping,Greatest N Per Group,假设我有一个名为Scrape的数据库表,可能设置如下: UserID (int) UserName (varchar) Wins (int) Losses (int) ScrapeDate (datetime) 我试图能够根据用户的胜负比对他们进行排名。然而,每周我都会搜集关于用户的新数据,并在Scrape表中输入另一个条目 如何查询按胜负排序的用户列表,但只考虑最近的输入日期 你也认为,人们会在网站上打牌吗? 例如,我可以: 1 - Bob - Wins: 320 - L

假设我有一个名为Scrape的数据库表,可能设置如下:

UserID (int)   
UserName (varchar)  
Wins (int)   
Losses (int)  
ScrapeDate (datetime)
我试图能够根据用户的胜负比对他们进行排名。然而,每周我都会搜集关于用户的新数据,并在Scrape表中输入另一个条目

如何查询按胜负排序的用户列表,但只考虑最近的输入日期

你也认为,人们会在网站上打牌吗? 例如,我可以:

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  
其中,这表示到目前为止只更新了Bob,并且正在更新Frank,但尚未插入。你会如何处理这种情况呢

所以,我的问题是:

您将如何处理仅查询每个用户的最新数据以确定排名 您是否认为数据库可能处于更新状态,特别是当一个scrape可能需要1天才能完成,并且并非所有用户都已完全更新时,这一事实是否重要?如果是这样,你会如何处理? 谢谢,谢谢你对我的相关问题的回答:


问题第一部分的答案取决于您使用的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
尝试以下方法:

为每个用户选择用户id和上次输入的最大日期。 根据以上查询结果,选择并排序记录以获得排名。 不过,这应该是可行的,这取决于您的数据库大小

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

我没有测试这段代码,所以它无法在第一次运行时编译。

这就是我所说的最大的每组n个问题。它每周在StackOverflow上出现几次

我使用外部连接技术解决此类问题:

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;
这将为每个用户名只返回一行-在scrapdate列中具有最大值的行。这就是外部联接的目的,尝试将s1与具有相同用户名和更大日期的其他行s2匹配。如果没有这样的行,则外部联接将为s2的所有列返回NULL,然后我们知道s1对应于给定用户名的日期最大的行

当您正在进行部分完成的刮伤时,这也应该起作用


这种技术不一定像其他答案给出的CTE和排名解决方案那样快速。你应该同时尝试这两种方法,看看哪种方法更适合你。我之所以喜欢我的解决方案,是因为它可以在任何类型的SQL中工作。

但是,SQL 7、SQL 2000、SQL 2005、SQL 2008、SQL 2008 R2是哪个版本?