Вложенная группа по LINQ

Я не могу решить эту проблему с помощью запроса LINQ.

Итак, у нас есть структура таблицы следующим образом:  Id || bug_category || bug_name || bug_details || bug_priority

Сначала я хочу группировать bug_category. Для каждой bug_category я хочу, в свою очередь, группировать bug__priority.

Так что в принципе я хочу что-то вроде:

bug_category = AUDIO:: No of BUGS → Critical = 3, Medium = 2 и Low = 7 ошибок.
 bug_category = VIDEO:: No of BUGS → Critical = 5, Medium = 1 и Low = 9 ошибок.

Следующий запрос возвращает все уникальные комбинации категории AND customer_priority:

(где RawDataList - это просто список данных, имеющий указанную выше структуру)

        var ProceesedData = from d in RawDataList
                      group d by new { d.bug_category, d.bug_priority } into g
                      select new
                      {
                          g.Key.bug_category,
                          g.Key.bug_priority
                      };

Следующий запрос возвращает категорию, за которой следует список записей в этой категории:

            var ProceesedData = from d in RawDataList
                      group d by d.bug_category into g
                      select new { g.Key, records = g
                      };

Но я не могу продолжить дальше, поскольку ProcessedData (возвращаемая переменная) является неизвестным типом. Любые мысли об этом?

Ответы

Ответ 1

Я подозреваю, что вы хотите (имена изменены, чтобы быть более идиоматичными):

var query = from bug in RawListData
            group bug by new { bug.Category, bug.Priority } into grouped
            select new { 
                Category = grouped.Key.Category,
                Priority = grouped.Key.Priority,
                Count = grouped.Count()
            };

Тогда:

foreach (var result in query)
{
    Console.WriteLine("{0} - {1} - {2}",
                      result.Category, result.Priority, result.Count);
}

Альтернативно (но см. ниже):

var query = from bug in RawListData
            group bug by new bug.Category into grouped
            select new { 
                Category = grouped.Category,
                Counts = from bug in grouped
                         group bug by grouped.Priority into g2
                         select new { Priority = g2.Key, Count = g2.Count() }
            };

foreach (var result in query)
{
    Console.WriteLine("{0}: ", result.Category);
    foreach (var subresult in result.Counts)
    {
        Console.WriteLine("  {0}: {1}", subresult.Priority, subresult.Count);
    }
}

EDIT: как отмечено в комментариях, это приведет к нескольким SQL-запросам. Чтобы получить аналогичную структуру результатов, но более эффективно, вы можете использовать:

var dbQuery = from bug in RawListData
              group bug by new { bug.Category, bug.Priority } into grouped
              select new { 
                  Category = grouped.Key.Category,
                  Priority = grouped.Key.Priority,
                  Count = grouped.Count()
              };

var query = dbQuery.ToLookup(result => result.Category,
                             result => new { result.Priority, result.Count };


foreach (var result in query)
{
    Console.WriteLine("{0}: ", result.Key);
    foreach (var subresult in result)
    {
        Console.WriteLine("  {0}: {1}", subresult.Priority, subresult.Count);
    }
}

Ответ 2

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

Предполагая, что у вас есть два свойства и вы хотите сгруппировать как по стране, так и по стране:

var grouped = People
  .GroupBy(l => new { l.State, l.Country})//group by two things
  .GroupBy(l=> l.Key.Country)//this will become the outer grouping


foreach(var country in grouped)
{
  foreach(var state in country)
  {
     foreach(var personInState in state)
     {
       string description = $"Name: {personInState.Name}, State: {state.StateCode}, Country: {country.CountryCode}";
       ...

     }
  }
}

Ответ 3

Я думаю, вы ищете что-то вроде этого:

    var processedData =
        rawData.GroupBy(bugs => bugs.bug_category,
            (category, elements) =>
            new
                {
                    Category = category,
                    Bugs = elements.GroupBy(bugs => bugs.bug_priority,
                                        (priority, realbugs) =>
                                        new
                                            {
                                                Priority = priority,
                                                Count = realbugs.Count()
                                            })
                });
    foreach (var data in processedData)
    {
        Console.WriteLine(data.Category);

        foreach (var element in data.Bugs)
            Console.WriteLine("  " + element.Priority + " = " + element.Count);
    }