假设我想按国家/地区对我的客户数据库进行排名。 在SQL中,我会写:
select CountryID, CustomerCount = count(*),
[Rank] = RANK() over (order by count(*) desc)
from Customer
现在我想在实体框架中编写以下内容:
var ranks = db.Customers
.GroupBy(c => c.CountryID)
.OrderByDescending(g => g.Count())
.Select((g, index) => new {CountryID = g.Key, CustomerCount = g.Count, Rank = index+1});
这有两个问题:
- 它不起作用。 EF 抛出一个
System.NotSupportedException
;显然,对于使用行号的重载.Select()
,没有 SQL 转换;您必须使用.ToList()
将所有内容拉入内存才能调用此方法;和 - 即使您在本地内存中运行该方法,它也不会像
RANK()
函数在 SQL 中那样处理相等的排名,即它们应该具有相等的排名,然后以下项跳到原始顺序。
那么我应该怎么做呢?
AFAIK Rank() 在 LINQ 中没有内置函数。这个答案使用你的方法,但它似乎对他们有用。 以下是使用它的方法:
var customersByCountry = db.Customers
.GroupBy(c => c.CountryID);
.Select(g => new { CountryID = g.Key, Count = g.Count() });
var ranks = customersByCountry
.Select(c => new
{
c.CountryID,
c.Count,
Rank = customersByCountry.Count(c2 => c2.Count > c.Count) + 1
});