用 linq 实现密集排名
implement dense rank with linq
使用以下 linq 代码,如何将 dense_rank 添加到我的结果中?如果那太慢或太复杂,那么 rank window 函数怎么样?
var x = tableQueryable
.Where(where condition)
.GroupBy(cust=> new { fieldOne = cust.fieldOne ?? string.Empty, fieldTwo = cust.fieldTwo ?? string.Empty})
.Where(g=>g.Count()>1)
.ToList()
.SelectMany(g => g.Select(cust => new {
cust.fieldOne
, cust.fieldTwo
, cust.fieldThree
}));
这样做 dense_rank()
。根据您的需要更改 GroupBy
和 Order
:)
基本上,dense_rank
是对查询的有序组进行编号,因此:
var DenseRanked = data.Where(item => item.Field2 == 1)
//Grouping the data by the wanted key
.GroupBy(item => new { item.Field1, item.Field3, item.Field4 })
.Where(@group => @group.Any())
// Now that I have the groups I decide how to arrange the order of the groups
.OrderBy(@group => @group.Key.Field1 ?? string.Empty)
.ThenBy(@group => @group.Key.Field3 ?? string.Empty)
.ThenBy(@group => @group.Key.Field4 ?? string.Empty)
// Because linq to entities does not support the following select overloads I'll cast it to an IEnumerable - notice that any data that i don't want was already filtered out before
.AsEnumerable()
// Using this overload of the select I have an index input parameter. Because my scope of work is the groups then it is the ranking of the group. The index starts from 0 so I do the ++ first.
.Select((@group , i) => new
{
Items = @group,
Rank = ++i
})
// I'm seeking the individual items and not the groups so I use select many to retrieve them. This overload gives me both the item and the groups - so I can get the Rank field created above
.SelectMany(v => v.Items, (s, i) => new
{
Item = i,
DenseRank = s.Rank
}).ToList();
另一种方法是 Manoj 在 this question 中的回答所指定的 - 但我不太喜欢它,因为从 table.
中选择了两次
所以如果我理解正确的话,密集排名是组的索引,当组被排序时。
var query = db.SomeTable
.GroupBy(x => new { x.Your, x.Key })
.OrderBy(g => g.Key.Your).ThenBy(g => g.Key.Key)
.AsEnumerable()
.Select((g, i) => new { g, i })
.SelectMany(x =>
x.g.Select(y => new
{
y.Your,
y.Columns,
y.And,
y.Key,
DenseRank = x.i,
}
);
使用以下 linq 代码,如何将 dense_rank 添加到我的结果中?如果那太慢或太复杂,那么 rank window 函数怎么样?
var x = tableQueryable
.Where(where condition)
.GroupBy(cust=> new { fieldOne = cust.fieldOne ?? string.Empty, fieldTwo = cust.fieldTwo ?? string.Empty})
.Where(g=>g.Count()>1)
.ToList()
.SelectMany(g => g.Select(cust => new {
cust.fieldOne
, cust.fieldTwo
, cust.fieldThree
}));
这样做 dense_rank()
。根据您的需要更改 GroupBy
和 Order
:)
基本上,dense_rank
是对查询的有序组进行编号,因此:
var DenseRanked = data.Where(item => item.Field2 == 1)
//Grouping the data by the wanted key
.GroupBy(item => new { item.Field1, item.Field3, item.Field4 })
.Where(@group => @group.Any())
// Now that I have the groups I decide how to arrange the order of the groups
.OrderBy(@group => @group.Key.Field1 ?? string.Empty)
.ThenBy(@group => @group.Key.Field3 ?? string.Empty)
.ThenBy(@group => @group.Key.Field4 ?? string.Empty)
// Because linq to entities does not support the following select overloads I'll cast it to an IEnumerable - notice that any data that i don't want was already filtered out before
.AsEnumerable()
// Using this overload of the select I have an index input parameter. Because my scope of work is the groups then it is the ranking of the group. The index starts from 0 so I do the ++ first.
.Select((@group , i) => new
{
Items = @group,
Rank = ++i
})
// I'm seeking the individual items and not the groups so I use select many to retrieve them. This overload gives me both the item and the groups - so I can get the Rank field created above
.SelectMany(v => v.Items, (s, i) => new
{
Item = i,
DenseRank = s.Rank
}).ToList();
另一种方法是 Manoj 在 this question 中的回答所指定的 - 但我不太喜欢它,因为从 table.
中选择了两次所以如果我理解正确的话,密集排名是组的索引,当组被排序时。
var query = db.SomeTable
.GroupBy(x => new { x.Your, x.Key })
.OrderBy(g => g.Key.Your).ThenBy(g => g.Key.Key)
.AsEnumerable()
.Select((g, i) => new { g, i })
.SelectMany(x =>
x.g.Select(y => new
{
y.Your,
y.Columns,
y.And,
y.Key,
DenseRank = x.i,
}
);