获取特定元素在有序表中的位置

时间:2018-09-19 11:46:19

标签: sql linq

我在对数据库中的球员进行排名时遇到了问题(至少以一种表现良好的方式)。

我有一个存储所有玩家的表格。玩家的等级取决于RankingPoints的数量。因此,(在最简单的情况下)玩家排名是此表中RankingPoints DESC排序的位置。 可能有多个玩家拥有相同的RankingPoints。因此,我需要一个决胜局,以使拥有200.000分的球员排名不会改变。

另一方面,根据球员的性别,年龄和国籍,我有一些子等级。

我该如何实时查看排名?我有一个男球员,来自德国的u18,我想知道他的国家/地区排名。

目前,我有这个针对U18CountryRank的子查询

U18CountryRank = Players // the database-table holding all players
    .Where(p => p.Gender == MainPlayer.Gender) // male
    .Where(p => p.Country == MainPlayer.Country) // Germany
    .Where(p => p.Classification == MainPlayer.Classification) // U18
    .Where(p => p.RankingPoints >= MainPlayerRankingPoints) // players better or equal than me
    .Where(p => SqlFunctions.Difference(p.PlayerId.ToString(), MainPlayer.PlayerId.ToString()) >= 0) // order by PlayerId
    .Count(); // take the number

这是生成的sql:

SELECT 
    1 AS [C1], 
    [Project1].[C1] AS [C2]
    FROM ( SELECT 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[Players] AS [Extent2]
            WHERE ([Extent2].[RankingPoints] >= [Extent1].[RankingPoints]) AND ([Extent2].[Gender] = [Extent1].[Gender]) AND ([Extent2].[Country] = [Extent1].[Country]) AND ((DIFFERENCE(LOWER( CAST( [Extent2].[PlayerId] AS nvarchar(max))), LOWER( CAST( [Extent1].[PlayerId] AS nvarchar(max))))) >= 0)) AS [C1]
        FROM [dbo].[Players] AS [Extent1]
        WHERE (cast('b8957470-db27-4b3c-aa5d-3035ca2c86e6' as uniqueidentifier) = [Extent1].[PlayerId])
    )  AS [Project1]

对单个玩家来说效果很好。但是当我需要选择某个国家/地区的所有球员时,表现将变得井井有条。

我已经尝试使用View,它仅选择PlayerId以及不同的等级。在大型电视机上的表现仍然很糟糕。

另一种方法是在有序子集上使用ROW_NUMBER(但在更大的子集上仍然存在相同的问题)。

针对此类问题的“最佳做法”是什么?

1 个答案:

答案 0 :(得分:0)

这是我在MainPlayer中查找男性,U18,德国的子等级的方法:

var RankOrderedPlayers = Players
                            .Where(p => p.Gender == MainPlayer.Gender) // male
                            .Where(p => p.Country == MainPlayer.Country) // Germany
                            .Where(p => p.Classification == MainPlayer.Classification) // U18
                            .OrderByDescending(p => p.RankingPoints)
                            .ThenByDescending(p => p.PlayerId)
                            .AsEnumerable()
                            .Select((p, r) => new { Rank = r+1, p });