implement dense rank with linq

前端 未结 2 2115
走了就别回头了
走了就别回头了 2020-12-10 22:41

Using the following linq code, how can I add dense_rank to my results? If that\'s too slow or complicated, how about just the rank window function?

var x = t         


        
相关标签:
2条回答
  • 2020-12-10 23:01

    So if I understand this correctly, the dense rank is the index of the group it would be when the groups are ordered.

    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,
            }
        );
    
    0 讨论(0)
  • 2020-12-10 23:04

    This does a dense_rank(). Change the GroupBy and the Order according to your need :) Basically, dense_rank is numbering the ordered groups of a query so:

    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();
    

    Another way is as specified by Manoj's answer in this question - But I prefer it less because of the selecting twice from the table.

    0 讨论(0)
提交回复
热议问题