2016-07-17 4 views
1

Используя следующий код linq, как я могу добавить dense_rank к моим результатам? Если это слишком медленно или сложно, как насчет функции окна ранга?реализовать плотный ранг с linq

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 
    })); 
+0

Ваш метод GroupBy не имеет смысла. Разве вы не должны указывать Func для извлечения ключа? –

+0

Что такое 'dense_rank'? – user3185569

+1

@TimothyGhanem Можете ли вы объяснить PLS? Я придерживался того же синтаксиса, что и http://www.codeducky.org/sql-queries-in-linq/#group-by –

ответ

2

Это 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(); 

Другим способ, как указано ответ Маноджа в this question - Но я менее предпочитаю это, потому что выбора дважды из таблицы.

+0

жаль, что это не сработало - –

+0

@MikeTurner - Отредактировано, что у вас больше полей. Вам не нужно добавлять 'AsQuerable' в конец, и вы должны иметь' AsEnumerable() 'после всех фильтров вашего' Where's. Этот пример должен работать. Если нет, попробуйте сначала создать список фиктивных элементов вашего класса и посмотреть, нужна ли ему логика. Только в конце действительно получить данные из базы данных и посмотреть –

+0

@GiladGreen этот код выглядит хорошо. Можете ли вы добавить комментарии, чтобы помочь понять вашу логику? –

1

Так что, если я правильно понимаю это, плотный ранг является индексом группы, когда они будут упорядочены.

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, 
     } 
    ); 
Смежные вопросы