选择多个字段分组并求和
Posted
技术标签:
【中文标题】选择多个字段分组并求和【英文标题】:Select multiple fields group by and sum 【发布时间】:2013-04-19 08:57:53 【问题描述】:我想使用 linq(对象列表)进行查询,但我真的不知道该怎么做,我可以进行分组和求和,但不能选择其余字段。 示例:
ID Value Name Category
1 5 Name1 Category1
1 7 Name1 Category1
2 1 Name2 Category2
3 6 Name3 Category3
3 2 Name3 Category3
我想按 ID 分组,按值 SUM 并返回所有这样的字段。
ID Value Name Category
1 12 Name1 Category1
2 1 Name2 Category2
3 8 Name3 Category3
【问题讨论】:
你有支票吗? code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b 和你的情况:code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b 由于每个 ID 的所有字段似乎都是唯一的,为什么不将它们也包含在组中。 是的,我可以这样做,但我有更多的字段... :( 通过这个链接..***.com/questions/847066/group-by-multiple-columns希望这能解决你的问题 【参考方案1】:更新:
如果您想避免对所有字段进行分组,您可以按Id
分组:
data.GroupBy(d => d.Id)
.Select(
g => new
Key = g.Key,
Value = g.Sum(s => s.Value),
Name = g.First().Name,
Category = g.First().Category
);
但此代码假定对于每个Id
,应用相同的Name
和Category
。如果是这样,您应该考虑按照@Aron 的建议进行规范化。这意味着将Id
和Value
保留在一个类中,并将Name
、Category
(以及相同Id
的任何其他字段相同)移动到另一个类,同时还具有Id
以供参考。规范化过程减少了数据冗余和依赖性。
【讨论】:
是的,我知道,但只是不想对所有字段进行分组,这将是一种不同的方式,我尝试使用 first() 但然后如何求和? 是的,我知道你在说什么,我有我的数据库规范化,这只是我查询的结果,但是对于我查询的每一行,我都有重复它的值,我想要将它们分组并总结价值。【参考方案2】:void Main()
//Me being lazy in init
var foos = new []
new Foo Id = 1, Value = 5,
new Foo Id = 1, Value = 7,
new Foo Id = 2, Value = 1,
new Foo Id = 3, Value = 6,
new Foo Id = 3, Value = 2,
;
foreach(var x in foos)
x.Name = "Name" + x.Id;
x.Category = "Category" + x.Id;
//end init.
var result = from x in foos
group x.Value by new x.Id, x.Name, x.Category
into g
select new g.Key.Id, g.Key.Name, g.Key.Category, Value = g.Sum();
Console.WriteLine(result);
// Define other methods and classes here
public class Foo
public int Id get;set;
public int Value get;set;
public string Name get;set;
public string Category get;set;
【讨论】:
我知道这种方式,但我不想在我的小组中有这么多领域,我有7个以上。 @user2112420 然后你将不得不规范你的课程。 这是我从多个表中进行的结果查询,并创建了一个这种类型的对象。 我只是从不同的表中进行查询,结果将是输入一个对象,通过该查询我创建了一个对象列表,因为在每一行中我都有 ID、名称、类别、值等。 如何从这些表中获得结果?如果您使用的是 ORM,您应该能够获得良好的规范化对象树。【参考方案3】:试试这个:
var objList = new List<SampleObject>();
objList.Add(new SampleObject() ID = 1, Value = 5, Name = "Name1", Category = "Catergory1");
objList.Add(new SampleObject() ID = 1, Value = 7, Name = "Name1", Category = "Catergory1");
objList.Add(new SampleObject() ID = 2, Value = 1, Name = "Name2", Category = "Catergory2");
objList.Add(new SampleObject() ID = 3, Value = 6, Name = "Name3", Category = "Catergory3");
objList.Add(new SampleObject() ID = 3, Value = 2, Name = "Name3", Category = "Catergory3");
var newList = from val in objList
group val by new val.ID, val.Name, val.Category into grouped
select new SampleObject() ID = grouped.ID, Value = grouped.Sum(), Name = grouped.Name, Category = grouped.Category ;
使用 LINQPad 检查:
newList.Dump();
【讨论】:
【参考方案4】:如果你的课真的很长而且你不想复制所有的东西,你可以试试这样:
l.GroupBy(x => x.id).
Select(x =>
var ret = x.First();
ret.value = x.Sum(xt => xt.value);
return ret;
).ToList();
能力越大,责任越大。你需要小心。 ret.value = x.Sum(xt => xt.value)
行 将改变您的原始集合,因为您传递的是引用,而不是新对象。如果你想避免它,你需要在你的类中添加一些Clone
方法,比如MemberwiseClone
(但同样,这会创建浅拷贝,所以要小心)。之后只需将行替换为:var ret = x.First().Clone();
【讨论】:
以上是关于选择多个字段分组并求和的主要内容,如果未能解决你的问题,请参考以下文章