DENSE_RANK () используя LINQ без промежуточных шагов - PullRequest
0 голосов
/ 09 марта 2020

У меня есть функция SQL SERVER RANK(), которая работает по следующему URL:

https://stackoverflow.com/questions/27469838/is-there-a-function-in-entity-framework-that-translates-to-the-rank-function-i?noredirect=1&lq=1

И, похоже, следующий ответ делает:

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

Я понял если я не могу напрямую получить DENSE_RANK(), я могу наблюдать, когда меняется RANK(), и пытаться выбрать DENSE_RANK() на основе этого

var denseRankCounter = 0;

Dictionary<int, int> denseRankWithRank = new Dictionary<int, int>();

denseRankWithRank.Add(customersByCountry[0].RANK, ++denseRankCounter);

for (int x = 1; x < customersByCountry.Count; x++)
{
    if (customersByCountry[x] != customersByCountry[x - 1])
    {
        if (!denseRankWithRank.ContainsKey(customersByCountry[x].RANK))
        {
            denseRankWithRank.Add(customersByCountry[x].RANK, ++denseRankCounter);
        }
    }
}

, а затем применить эти результаты обратно к набору результатов. ,

var denseCustomersByCountry = customersByCountry.Select(c => new
                            {
                                DENSE_RANK = denseRankWithRank[c.RANK],
                                CountryID = c.CountryID
                                // ...  ,any other required 
                            }).ToList();

Хотя это работает несколько, это кажется очень громоздким.
Мне было интересно, есть ли более простой способ без словаря или каких-либо промежуточных шагов.

Ответы [ 2 ]

1 голос
/ 09 марта 2020

Попробуйте следующее:

            var customersByCountry = db.Customers
                .GroupBy(c => c.CountryID)
                .OrderByDescending(x => x.Count())
                .Select((g,rank) => new { CountryID = g.Key, Count = g.Count(), Rank = rank });
0 голосов
/ 09 марта 2020

Это было не слишком сложно.
Я заставил его работать, используя вышеописанный подход jdweng, поэтому я отметил это как ответ.
В моих фактических результатах работы с БД groupBy был очень медленным, поэтому я создал подмножество полей, затем сделал фактическую группировку.

var customers = db.Customers.OrderBy(c=>c.CountryID);

    var ranks = customers.Select(c => new 
                                  { 
                                        c.CountryID, 
                                        c.Count, 
                                        RANK = customers.Count(c2 => c2.Count > c.Count) + 1
                                    });


    var denseCustomersByCountry = ranks.GroupBy(r => r.RANK)
                                            .Select((r, idx) => new
                                            {
                                                RANK = r.Key,
                                                COUNT = r.Count(),
                                                DENSE_RANK = idx + 1,
                                                CountryID = r.FirstOrDefault().CountryID
                                            })
                                            .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...