使用 Linq 将 DataTable 项目到新结构中



我有一个数据表,我想按摩成一种新的格式(这是它附加到网格视图时的样子):

 <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 | Sum(Actual) | Sum(Target)
FFAC            | 1000        | 2000
FHHT            | 200         | 175

任何指导将不胜感激!

问候

克里斯

你不会在这里做任何按摩;)

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"))
               });

Oi,我认为这会比预期的更困难,但最终变得更容易,我重写了这个。您在行上执行分组,但随后只需查询每个组中的行即可获取产品类别。

首先,您将按主键分组,在本例中,我相信主键是Line列。所以:

myDataTable.AsEnumerable()
    .GroupBy(m => m.Field<string>("Line"))

接下来,我们必须找到每个分组的类别。由于每个分组都是一个IEnumerable<T>,只需在将我们的Attribute过滤为ProductCategory并获取第一个值后执行Select。我使用了一些"防御性"编码,考虑不存在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)分组到其他组中。真的没有一个简单的方法,而且选项也不漂亮。事实上,您必须对每个组进行分组,但为了对组进行分组,您必须在组中查询单个实体,然后基于另外 2 个实体进行聚合(这使得在此处使用 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)
        })

再次,不是很漂亮...特别是由于您的"值"列是字符串,您必须解析它们才能获得有意义的值(在本例中为对数字求和)。这里的前提是将所有记录分组到"块"中,然后将这些块组合成单个匿名对象。因此,每个匿名对象都表示特定行的所有数据行属性/值对。从那里,您只需根据所需的键(在本例中为产品类别)进行分组,然后执行所需的聚合。

PS,我实际上会使用 PIVOT 在数据库端执行此查询。可能需要更多设置,但随后您为设计用于执行此类数据处理/聚合的系统提供它可以处理的工作,并保持前端 CPU 周期以用于更重要的事情。

相关内容

  • 没有找到相关文章

最新更新