按多列分组

Sre*_*har 919 .net c# linq group-by aggregate

如何在LINQ中执行GroupBy多列

SQL中与此类似的东西:

SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>
Run Code Online (Sandbox Code Playgroud)

如何将其转换为LINQ:

QuantityBreakdown
(
    MaterialID int,
    ProductID int,
    Quantity float
)

INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity)
SELECT MaterialID, ProductID, SUM(Quantity)
FROM @Transactions
GROUP BY MaterialID, ProductID
Run Code Online (Sandbox Code Playgroud)

lep*_*pie 1165

使用匿名类型.

例如

group x by new { x.Column1, x.Column2 }
Run Code Online (Sandbox Code Playgroud)

  • 如果您刚开始使用匿名类型进行分组,则在此示例中使用"new"关键字会产生魔力. (28认同)
  • 如果mvc与nHibernate获取dll问题的错误.GroupBy解决的问题(x => new {x.Column1,x.Column2},(key,group)=> new {Key1 = key.Column1,Key2 = key.Column2,Result = group.ToList()}); (7认同)
  • @HoGo匿名类型对象[实现自己的Equals和GetHashCode](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types)使用的方法分组对象时. (4认同)

Mo0*_*les 727

程序样本

.GroupBy(x => new { x.Column1, x.Column2 })
Run Code Online (Sandbox Code Playgroud)

  • @Tom这应该按照它的方式工作.当您跳过命名匿名类型的字段时,C#假定您要使用投影中最终访问的属性/字段的名称.(所以你的例子相当于Mo0gles') (19认同)
  • @MGG_Soft将是一个匿名类型 (5认同)

Sre*_*har 452

好吧得到这个:

var query = (from t in Transactions
             group t by new {t.MaterialID, t.ProductID}
             into grp
                    select new
                    {
                        grp.Key.MaterialID,
                        grp.Key.ProductID,
                        Quantity = grp.Sum(t => t.Quantity)
                    }).ToList();
Run Code Online (Sandbox Code Playgroud)

  • +1 - 感谢您提供全面的示例.另一个答案的片段太短,没有上下文.您还显示了一个聚合函数(在本例中为Sum).很有帮助.我发现聚合函数(即MAX,MIN,SUM等)与分组并排使用是常见的情况. (74认同)

Mil*_*lan 141

对于按多列分组,请尝试此操作...

GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new 
{ 
  Key1 = key.Column1,
  Key2 = key.Column2,
  Result = group.ToList() 
});
Run Code Online (Sandbox Code Playgroud)

以同样的方式添加Column3,Column4等.

  • 这非常有帮助,应该得到更多的赞成!`Result`包含链接到所有列的所有数据集.非常感谢! (4认同)

小智 26

从C#7开始,你也可以使用值元组:

group x by (x.Column1, x.Column2)
Run Code Online (Sandbox Code Playgroud)

要么

.GroupBy(x => (x.Column1, x.Column2))
Run Code Online (Sandbox Code Playgroud)

  • 好吧,我认为你最后错过了一个额外的).你没有关闭() (2认同)
  • .GroupBy(x =&gt; new {x.Column1,x.Column2}) (2认同)

Jay*_*enu 17

您还可以使用元组<>进行强类型分组.

from grouping in list.GroupBy(x => new Tuple<string,string,string>(x.Person.LastName,x.Person.FirstName,x.Person.MiddleName))
select new SummaryItem
{
    LastName = grouping.Key.Item1,
    FirstName = grouping.Key.Item2,
    MiddleName = grouping.Key.Item3,
    DayCount = grouping.Count(), 
    AmountBilled = grouping.Sum(x => x.Rate),
}
Run Code Online (Sandbox Code Playgroud)

  • 注意:Linq To Entities不支持创建新元组 (4认同)

Alb*_*rtK 12

C#7.1或更大的使用TuplesInferred tuple element names(目前它只能linq to objects当需要表达式树例如,它不支持someIQueryable.GroupBy(...)Github的问题):

// declarative query syntax
var result = 
    from x in table
    group x by (x.Column1, x.Column2) into g
    select (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity));

// or method syntax
var result2 = table.GroupBy(x => (x.Column1, x.Column2))
    .Select(g => (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity)));
Run Code Online (Sandbox Code Playgroud)

C#3或更高版本,可使用anonymous types

// declarative query syntax
var result3 = 
    from x in table
    group x by new { x.Column1, x.Column2 } into g
    select new { g.Key.Column1, g.Key.Column2, QuantitySum = g.Sum(x => x.Quantity) };

// or method syntax
var result4 = table.GroupBy(x => new { x.Column1, x.Column2 })
    .Select(g => 
      new { g.Key.Column1, g.Key.Column2 , QuantitySum= g.Sum(x => x.Quantity) });
Run Code Online (Sandbox Code Playgroud)

  • 哇谢谢你。这在大脑中留下了印记,并增加了可能性的能力。 (2认同)

Chr*_*ith 8

虽然这个问题是按类属性询问,但是如果要针对ADO对象(如DataTable)按多个列进行分组,则必须将"新"项分配给变量:

EnumerableRowCollection<DataRow> ClientProfiles = CurrentProfiles.AsEnumerable()
                        .Where(x => CheckProfileTypes.Contains(x.Field<object>(ProfileTypeField).ToString()));
// do other stuff, then check for dups...
                    var Dups = ClientProfiles.AsParallel()
                        .GroupBy(x => new { InterfaceID = x.Field<object>(InterfaceField).ToString(), ProfileType = x.Field<object>(ProfileTypeField).ToString() })
                        .Where(z => z.Count() > 1)
                        .Select(z => z);
Run Code Online (Sandbox Code Playgroud)