web-dev-qa-db-fra.com

Groupe imbriqué par LINQ

Je suis incapable de résoudre ce problème avec la requête LINQ. 

Nous avons donc la structure de table suivante: Id || bug_category || bug_name || bug_details || bug_priority

Je veux d'abord grouper par bug_category. Pour chaque catégorie de bug, je veux à mon tour grouper par bug__priority.

Donc, fondamentalement, je veux quelque chose comme:

bug_category = AUDIO :: Nb de BOGUES -> Critique = 3, Moyen = 2 et Bas = 7 bogues.
bug_category = VIDEO :: N ° de BOGUES -> Critique = 5, Moyen = 1 et Faible = 9 bogues.

La requête ci-dessous renvoie toutes les combinaisons uniques de la catégorie ET de la priorité client:

(où RawDataList est simplement une liste de données ayant la structure susmentionnée)

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

La requête ci-dessous renvoie la catégorie, suivie d'une liste des enregistrements de cette catégorie:

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

Mais je suis incapable de continuer car ProcessedData (la variable de retour) est un type inconnu. Des idées à ce sujet?

19
Nandu

Je suppose que vous voulez (les noms ont été changés pour être plus idiomatiques):

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

Ensuite:

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

Alternativement (mais voir plus tard):

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: Comme indiqué dans les commentaires, cela entraînera plusieurs requêtes SQL. Pour obtenir une structure de résultats similaire mais plus efficace, vous pouvez utiliser:

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);
    }
}
28
Jon Skeet

C'est un moyen plus facile de réaliser des groupes imbriqués. Je l’ai testée dans les collections de mémoire. Il est impossible de savoir si votre fournisseur de base de données le gérera bien, ou si son fonctionnement est inconnu.

En supposant que vous ayez deux propriétés et que vous souhaitiez les regrouper par État et par pays:

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}";
       ...

     }
  }
}
24
AaronLS

Je pense que vous cherchez quelque chose comme ça:

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

Tu peux le faire comme ça

 var retList = (from dbc in db.Companies
                           where dbc.IsVerified && dbc.SellsPCBs && !dbc.IsDeleted && !dbc.IsSpam && dbc.IsApproved
                           select new
                           {
                               name = dbc.CompanyName,
                               compID = dbc.CompanyID,
                               state = dbc.State,
                               city = dbc.City,
                               businessType = dbc.BusinessType
                           }).GroupBy(k => k.state).ToList();


            List<dynamic> finalList = new List<dynamic>();

            foreach (var item in retList)
            {
                finalList.Add(item.GroupBy(i => i.city));
            }
0
bhavsar japan