【问题标题】:how to add other fields to group by linq如何将其他字段添加到按l​​inq分组
【发布时间】:2020-09-15 06:33:37
【问题描述】:

我必须选择和分组,因为我需要获取某些项目的平均值和总和,我的问题首先是分组是基于月份(m_date.Month)所以在分组内我不可以访问 year 了,我的第二个问题是如果我想在我的查询中拥有来自 statisticsDaily 类的其他属性怎么办?使用此查询,我只能访问按字段分组,请看下面:

 var rslt = await (from d in db.statMonth.Include(f=>f.MasterData).Where(d=>d.m_turbine_id == IPAddress.Parse(id) && d.m_date >= frm)
                          group d by d.m_date.Month into g 
                          select new statisticsDaily
                          {
                              Date = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key),
                              Production = g.Sum(s => s.m_energy_prod),
                              m_wind_speed = g.Average(s => s.m_wind_speed),
                              Availability = g.Average(s => s.m_availability),              
                          }
             ).OrderBy(s=>s.Date).ToListAsync(); 

我的 statsticDaily 课程是:

         public class statisticsDaily
        {
            public string Date { get; set; }
            public Nullable<float> Production { get; set; }
            public Nullable<float> m_wind_speed { get; set; }
            public Nullable<float> Availability { get; set; }
            public string Comments { get; set; }
            public string TurbineId { get; set; }
            public string Countries { get; set; }
            
        }

【问题讨论】:

    标签: linq


    【解决方案1】:

    这正是group by 的工作原理。如果您也需要访问Year,那么您需要将MonthYear 分组在一起:

     var rslt = await (from d in db.statMonth.Include(f=>f.MasterData).Where(d=>d.m_turbine_id == IPAddress.Parse(id) && d.m_date >= frm)
                              group d by new { d.m_date.Month, d.m_date.Year} into g 
                              select new statisticsDaily
                              {
                                  Year = g.Key.Year// We can access Year now since we grouped by Year as well
                                  Date = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key.Month),
                                  Production = g.Sum(s => s.m_energy_prod),
                                  m_wind_speed = g.Average(s => s.m_wind_speed),
                                  Availability = g.Average(s => s.m_availability),              
                              }
                 ).OrderBy(s=>s.Date).ToListAsync(); 
    

    见:Using group by on multiple columns

    另一方面,您可以在按项目分组时以g.ToList() 访问其他属性列表。见:LINQ Group By and select collection

    【讨论】:

    • 我怎么能有其他的statisticsDaily类字段呢?我不应该对它们应用聚合函数只需要选择它们,我需要的字段是评论和国家
    • 您可以使用SelectToList 访问“其他”项目列表,我已添加回答,
    • 对不起,我没有得到最后一部分,我如何将其他统计字段添加到该组?一个字段是国家,我应该说国家=g.ToList()?!
    • 应该是这样的,例如Countries = g.Select(i=&gt;i.Country)。 (由于您没有添加类定义,我不确切知道您想要哪些属性,但我想您明白了..)
    • 这给了我一个错误,它无法从 Ienumerable 转换为字符串,当我执行 Country = g.Select(i=>i.Country).ToString() 时出现错误 500(server) ,我已将我的课程添加到我的问题中
    【解决方案2】:

    每个 StatMonth 都有一个属性 m_Date。您的 GroupBy 将 StatMonths 分组为 m_Date.Month 具有相同的值。

    因此,m_Date 为 2019 年 2 月的 StatMonth 将与所有 m_Date 为 2020 年 2 月和 2018 年 2 月的 StatMonth 位于同一组中。

    你写道:

    ...所以在 group by 我再也无法访问 year 了,

    这取决于你想对这一年做什么。

    • 您想在同一年的同一月份使用 m_Date 将 StatMonths 分组吗?那么,您要制作一组 2019-02、2019-03、2019-04、...、2020-02、2020-03 等的 StatMonths 吗?
    • 或者您是否要创建一个 2 月组的子组:2019 年子组、2020 年子组等。类似地,3 月组与 2019 年子组、2020 年子组。

    如果您查看 GroupBy 的通用方法语法,您会看到以下内容:

    var result = db.StatMonths
        .Where(...)
        .GroupBy(
            // parameter KeySelector: I want to make Groups of StatMonths that have the 
            // same value for this key:
            statMonth => ... // this will be the key,
    
            // for example: groups with same Year/Month combination of m_Date
            statMonth => new 
            {
               Year = statMonth.m_Date.Year,
               Month = statMonth.m_Date.Month,
            },
    
            // parameter resultSelector, for every Key, and all StatMonths that have this key
            // make one new object:
            (yearMonthCombination, statMonthsWithThisYearMonthCombination) => new ...
    }
    

    所以在参数resultSelector中,你得到了key,以及所有拥有这个key的item。因此,如果您需要具有相同年/月组合的组,请按上述方式创建一个键。如果您想为所有年份创建具有相同月份的组,并且每年创建子组:

    // parameter keySelector: make groups with same month, for all year:
    statMonth => stathMonth.m_Date.Month,
    
    // parameter resultSelector: take the key and all statMonths with this key to make a new
    (month, statMonthsWithThisMonth) => new
    {
         Month = month,
    
         SubGroups = statMonthsWithThisMonth.GroupBy(
             // make subgroups with same Year,
             // all statMonths in this group already have the same month
             statMonth => statMonth.m_Date.Year,
    
             // parameter resultSelector: use the year, and all statMonths of the group
             // with this year
             (year, statMonthisWithThisYear) => new
             {
                  Year = year,
                  ... // other statMonth
             })
      })
    

    除了在你的例子中你没有说你想做的事情,所以我不知道是制作一个具有相同年/月组合的组序列还是一个具有相同月份子组的序列同年。

    恕我直言,后者在不添加太多功能的情况下更难看出发生了什么。

    【讨论】:

    • 感谢您的完整回答,我已经通过添加课程更新了我的问题,如果您在我的课程中看到我有一些字段,我必须应用聚合函数,这就是我分组的原因,我有其他字段,如 Cointry 和 cmets,我怎样才能在这个查询中也有它们?如果我说 Comments=g.select(s=>s.Comments) 我得到错误,你可以从 IEnumerable 转换为 String,如果说转换为字符串我在浏览器中得到错误 500
    • 也许您应该编辑问题并用文字写出要求:“给定StatMonths 的序列,将Statmonths 组成一组具有相同值的...为每个组做一个StatisticsDaily that ..." 只要你不给出你的要求,我们就不能说你应该分组什么,你应该在你的结果选择器中选择什么。
    • 关于字符串错误。您似乎喜欢使用不描述它们的标识符。自己想想:在Comments=g.Select(s=&gt;... 中,g 是什么?什么是s?答案:g 是一组Statmonths,具有相同的值...因此,s 是一个Statmonth。从此StatMonth 中选择Comments,它是一个字符串。因此 Select 的结果是一个字符串序列。是什么让您认为可以将一系列字符串分配给您的 Comments
    猜你喜欢
    • 2012-07-01
    • 2019-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多