我有一个DataTable我想按摩到一种新的格式(这就是它附加到gridview时的结果):
<table cellspacing="0" rules="all" border="1" id="GridView1" style="border-collapse: collapse;">
<tr>
<th scope="col">
Line
</th>
<th scope="col">
StartTime
</th>
<th scope="col">
EndTime
</th>
<th scope="col">
Attribute
</th>
<th scope="col">
Value
</th>
</tr>
<tr>
<td>
Line1
</td>
<td>
24/01/2013 7:30:10 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Actual
</td>
<td>
0
</td>
</tr>
<tr>
<td>
Line1
</td>
<td>
24/01/2013 7:30:10 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
ProductCategory
</td>
<td>
FFAC
</td>
</tr>
<tr>
<td>
Line1
</td>
<td>
24/01/2013 7:30:10 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Target
</td>
<td>
36.5
</td>
</tr>
<tr>
<td>
Line2
</td>
<td>
24/01/2013 7:26:50 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Actual
</td>
<td>
69
</td>
</tr>
<tr>
<td>
Line2
</td>
<td>
24/01/2013 7:26:50 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
ProductCategory
</td>
<td>
FFAC
</td>
</tr>
<tr>
<td>
Line2
</td>
<td>
24/01/2013 7:26:50 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Target
</td>
<td>
55.5555582046509
</td>
</tr>
<tr>
<td>
Line3
</td>
<td>
24/01/2013 8:00:20 AM
</td>
<td>
24/01/2013 8:47:50 AM
</td>
<td>
Actual
</td>
<td>
1475
</td>
</tr>
<tr>
<td>
Line3
</td>
<td>
24/01/2013 8:00:20 AM
</td>
<td>
24/01/2013 8:47:50 AM
</td>
<td>
ProductCategory
</td>
<td>
FFAC
</td>
</tr>
<tr>
<td>
Line3
</td>
<td>
24/01/2013 8:00:20 AM
</td>
<td>
24/01/2013 8:47:50 AM
</td>
<td>
Target
</td>
<td>
202.430557310581
</td>
</tr>
<tr>
<td>
Line4
</td>
<td>
24/01/2013 7:31:30 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Actual
</td>
<td>
1384
</td>
</tr>
<tr>
<td>
Line4
</td>
<td>
24/01/2013 7:31:30 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
ProductCategory
</td>
<td>
FFAC
</td>
</tr>
<tr>
<td>
Line4
</td>
<td>
24/01/2013 7:31:30 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Target
</td>
<td>
3179.26381587982
</td>
</tr>
<tr>
<td>
Line5
</td>
<td>
24/01/2013 7:37:00 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Actual
</td>
<td>
0
</td>
</tr>
<tr>
<td>
Line5
</td>
<td>
24/01/2013 7:37:00 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
ProductCategory
</td>
<td>
FHHT
</td>
</tr>
<tr>
<td>
Line5
</td>
<td>
24/01/2013 7:37:00 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Target
</td>
<td>
92.6652171770756
</td>
</tr>
<tr>
<td>
P2_Bundler
</td>
<td>
24/01/2013 7:35:00 AM
</td>
<td>
24/01/2013 8:00:10 AM
</td>
<td>
Actual
</td>
<td>
7
</td>
</tr>
</table>
我知道如果记录具有相同的行,开始和结束时间,则记录是相关的。
我想要做的是获取ProductCategory分组的Actual和Target值的总和。换句话说:
ProductCategory | Sum(Actual) | Sum(Target)
FFAC | 1000 | 2000
FHHT | 200 | 175
任何指导都将不胜感激!
此致
克里斯
答案 0 :(得分:2)
你不会在这里按摩;)
dataTable的结构比网格代码更有用,但是为了从DataTable中获得你想要的东西,你应该做类似的事情。
var result = myDataTable.AsEnumerable()
.GroupBy(m => m.Field<string>("ProductCategory"))
.Select(g => new {
productCategory = g.Key,
sumActual = g.Sum(x => x.Field<decimal>("Actual")),
sumTarget = g.Sum(x => x.Field<decimal>("Target"))
});
答案 1 :(得分:0)
首先,您要按主键分组,在这种情况下,我认为是Line
列。所以:
myDataTable.AsEnumerable()
.GroupBy(m => m.Field<string>("Line"))
接下来,我们必须找到每个分组的类别。由于每个分组都是IEnumerable<T>
,因此在将Select
过滤为Attribute
后,只需执行ProductCategory
并获取第一个值。我用了一点&#34;防守&#34;通过考虑不存在ProductCategory
属性的情况进行编码:
...
.Select(g => new
{
ProductCategory = g.Where(r => r.Field<string>("Attribute") == "ProductCategory")
.Select(r => r.Field<string>("Value"))
.FirstOrDefault() ?? "No Category",
SumActual = g.Sum(x => x.Field<decimal>("Actual")),
SumTarget = g.Sum(x => x.Field<decimal>("Target"))
})
编辑:好的,现在我看到你在说什么了。我的原始想法是正确的,因为您将每个原始组(基于Line)分组到更多组中。这真的不是一个简单的方法,而且选项也不是很好。事实上你必须对每个组进行分组,但是为了对组进行分组,你必须在组中查询单个实体,然后根据另外两个实体进行聚合(这里很难使用LINQ) )。
myDataTable.AsEnumerable()
.GroupBy(m => m.Field<string>("Line"))
.Select(g => new
{
ProductCategory = g.Where(r => r.Field<string>("Attribute") == "ProductCategory")
.Select(r => r.Field<string>("Value"))
.FirstOrDefault() ?? "No Category",
Actual = g.Where(r => r.Field<string>("Attribute") == "Actual")
.Select(r =>
{
decimal d = 0m;
Decimal.TryParse(r.Field<string>("Value"), out d);
return d;
}
.FirstOrDefault(),
Target = g.Where(r => r.Field<string>("Attribute") == "Target")
.Select(r =>
{
decimal d = 0m;
Decimal.TryParse(r.Field<string>("Value"), out d);
return d;
}
.FirstOrDefault()
})
.GroupBy(n => n.ProductCategory)
.Select(g => new
{
ProductCategory = g.Key,
SumActual = g.Sum(x => x.Actual),
SumTarget = g.Sum(x => x.Target)
})
再次,不是很漂亮......特别是因为你的价值&#34; column是字符串,您必须解析它们才能获得有意义的值(在这种情况下,将数字相加)。这里的前提是你将所有记录分组到&#34; blocks&#34;,然后将这些块组成单个匿名对象。因此,每个匿名对象代表特定Line的所有datarow属性/值对。从那里,您只需根据所需的密钥(在本例中为ProductCategory)进行分组,并执行所需的聚合。
PS,我实际上会使用PIVOT在数据库端执行此查询。可能需要更多的设置,但是然后你给系统设计执行这种类型的数据处理/聚合它可以处理的工作,并保持你的前端CPU周期更重要。