【问题标题】:Nested Group by LINQLINQ 的嵌套组
【发布时间】:2012-03-06 06:21:48
【问题描述】:

我无法使用 LINQ 查询解决此问题。

所以我们的表结构如下: 编号 ||错误类别 ||错误名称 ||错误详细信息 || bug_priority

我想先按 bug_category 分组。对于每个 bug_category,我想依次按 bug__priority 分组。

所以基本上我想要类似的东西:

bug_category = AUDIO :: No of BUGS --> 严重 = 3,中等 = 2 和低 = 7 个错误。
bug_category = VIDEO :: No of BUGS --> 严重 = 5,中等 = 1 和低 = 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(返回变量)是未知类型。对此有什么想法吗?

【问题讨论】:

    标签: c# sql linq group-by


    【解决方案1】:

    这是完成嵌套分组的一种更简单的方法。我已经在内存集合中对其进行了测试,您的特定数据库提供商是否能很好地处理它可能会有所不同,或者它是否表现良好是未知的。

    假设您有两个属性,并且想按州和国家/地区分组:

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

    【讨论】:

    • 这是一个很难找到的答案!
    • 是的,当我自己需要这个时,我花了一段时间才弄清楚这一点,当我需要这样做时,我实际上会回到自己的答案。
    【解决方案2】:

    我怀疑你想要(名字改得更惯用了):

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

    编辑:如 cmets 中所述,这将导致多个 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);
        }
    }
    

    【讨论】:

    • 第二个查询将为每个组创建一个辅助查询,所以我认为更好的解决方案是第一个查询,然后是 ToLookup by category
    • @AdrianIftode:你试过了吗?我没有,但我预计会生成适当的 SQL 以一次性完成所有操作。
    • 是的,使用 LinqPad,一个查询类别组和其他 X 查询优先级组
    • @AdrianIftode:对 - 届时将对其进行编辑。我想知道在 EF 中是否会发生同样的事情......
    • 不,它在主要组和次要组之间进行外部应用(在外部应用连接中使用主要组键),因此在这种情况下为 EF +1(与许多其他情况一样)跨度>
    【解决方案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);
        }
    

    【讨论】:

    • @Nandu:你意识到这与我的第二个查询基本相同,只是采用 lambda 表达式形式,对吧?请注意,它的性能与 Adrian 指出的相同(因为它是相同的查询)。
    • 比 Jon Skeet 多花 9 分钟来写答案的危险 ;)
    【解决方案4】:

    你可以这样做

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多