Group By Multiple Columns
如何在Linq中进行GroupBy多列
在SQL中与此类似的东西:
1 | SELECT * FROM <TableName> GROUP BY <Column1>,<Column2> |
如何将此转换为LINQ:
1 2 3 4 5 6 7 8 9 10 11 | QuantityBreakdown ( MaterialID int, ProductID int, Quantity float ) INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity) SELECT MaterialID, ProductID, SUM(Quantity) FROM @Transactions GROUP BY MaterialID, ProductID |
使用匿名类型。
如
1 | group x by new { x.Column1, x.Column2 } |
程序性样本
1 | .GroupBy(x => new { x.Column1, x.Column2 }) |
好吧,这样做是:
1 2 3 4 5 6 7 8 9 | 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(); |
对于按多个列分组,请尝试此操作…
1 2 3 4 5 6 | GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new { Key1 = key.Column1, Key2 = key.Column2, Result = group.ToList() }); |
同样,您可以添加第3列、第4列等。
由于c 7,您还可以使用值元组:
1 | group x by (x.Column1, x.Column2) |
或
1 | .GroupBy(x => (x.Column1, x.Column2)) |
还可以使用元组<>进行强类型分组。
1 2 3 4 5 6 7 8 9 | 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), } |
尽管此问题询问的是按类分组属性,但如果要针对ADO对象(如数据表)按多个列分组,则必须将"新"项分配给变量:
1 2 3 4 5 6 7 | 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); |
1 | var Results= query.GroupBy(f => new { /* add members here */ }); |
C 7.1或更高版本,使用
1 2 3 4 5 6 7 8 9 | // 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))); |
c 3或更高版本,使用
1 2 3 4 5 6 7 8 9 10 | // 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) }); |
X组按新的X.列,X.列
1 | .GroupBy(x => x.Column1 +"" + x.Column2) |
需要注意的是,您需要为lambda表达式发送一个对象,并且不能为类使用实例。
例子:
1 2 3 4 5 6 | public class Key { public string Prop1 { get; set; } public string Prop2 { get; set; } } |
这将编译,但每个循环将生成一个键。
1 2 3 4 5 | var groupedCycles = cycles.GroupBy(x => new Key { Prop1 = x.Column1, Prop2 = x.Column2 }) |
如果您不想命名密钥属性,然后检索它们,您可以这样做。这将正确地执行cx1〔1〕,并为您提供关键属性。
1 2 3 4 5 6 7 8 9 10 11 12 | var groupedCycles = cycles.GroupBy(x => new { Prop1 = x.Column1, Prop2= x.Column2 }) foreach (var groupedCycle in groupedCycles) { var key = new Key(); key.Prop1 = groupedCycle.Key.Prop1; key.Prop2 = groupedCycle.Key.Prop2; } |