使用Linq将Project DataTable转换为新结构

时间:2013-01-24 15:29:08

标签: linq

我有一个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

任何指导都将不胜感激!

此致

克里斯

2 个答案:

答案 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)

Oi,我认为这比预期的要困难,但最终变得更容易,我重写了这一点。您在该行上执行分组,但是您只需要查询每个组中的行以获取ProductCategory。

首先,您要按主键分组,在这种情况下,我认为是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周期更重要。