【问题标题】:Sum columns in datatable based on values from another column根据另一列的值对数据表中的列求和
【发布时间】:2012-09-23 21:10:47
【问题描述】:

我有一个数据库表,用作报告的来源。表格布局看起来 喜欢。表 1 是一个更大的数据库表的子集。但是对于报告我只需要某些列所以我正在使用下面给出的函数创建一个新的数据表

Value  Description   Hours
    1          A           2
    2          B           3
    3          C           5
    1          A           3
    2          B           4
    2          B           3
    3          C           3


private DataTable CreateFocusOfEffortData()
    {
        var dtChartData = new DataTable();
        dtChartData.Columns.Add("Description", typeof(string));
        dtChartData.Columns.Add("Hours", typeof(Double));
        var myDataView = ReportData.DefaultView;
        myDataView.RowFilter = "ActivityUnitID = " + _ActivityUnitID;
        for (var i = 0; i < myDataView.ToTable().Rows.Count; i++)
        {
            var dataRow = new Object[dtChartData.Columns.Count];
            dataRow[0] = ReportData.Rows[i]["Description"];
            dataRow[1] = csaConvert.ToDouble(ReportData.Rows[i]["Hours"]);
            dataRow[2] = ReportData.Rows[i]["Value"];
            dtChartData.Rows.Add(dataRow);
        }
        return dtChartData;
    }

现在我需要使用上表中的汇总数据设计另一个报告。该表应 根据 Column["Value] 组合所有列的数据。例如,在我的情况下,我们在 Value 列 1、2、3 中有三个不同的值。生成的表应该有所有三个值的小时数。

    Value   Description  Hours
    1         A           5
    2         B           10
    3         C           8

现在我可以通过创建另一个存储过程在 sql 中执行此操作,但我宁愿使用我现有的数据表并编写一个 C# 函数来获取结果。有没有更简单的方法可以使用 LINQ 实现这一目标?

【问题讨论】:

    标签: c# sql


    【解决方案1】:

    您采取了错误的方法。在 SQL 中完成这项工作。

     SELECT value, description, sum(hours) as hours from tblData group by value, description;
    

    上面将为您提供您在问题中显示的第二个表格。

    这样做的原因是,将数据传递给客户端应用程序只是为了将其直接传递回 SQL,这会不必要地消耗内存和系统调用。此外,错误、错误、类型转换问题等的空间要小得多。

    如果您真的想制作更窄的表格(这通常是个坏主意),请这样做:

     SELECT value, description, hours from tblData into tblSkinnyData;
    

    一般来说,如果您出于某种原因需要这个瘦表,您会在主表上使用 VIEW。

    【讨论】:

    • 感谢您的建议。我通常会使用 sql 对数据表进行任何操作。但这次我不得不用代码来做。此外,数据只被传递给客户端应用程序一次,即在页面加载时。一旦我有了我的大数据表,我就会使用代码从中提取小表。
    【解决方案2】:

    您可以使用AsEnumerable() 来使用LINQ,然后通过ValueDescription 使用GroupBy 并在Hours 上执行Sum 以设置第一行:

    var result = dtChartData.AsEnumerable()
                .GroupBy(row => new
                    {
                        Value = row.Field<int>("Value"),
                        Description = row.Field<string>("Description")
                    })
                .Select(g =>
                    {
                        var row = g.First();
                        row.SetField("Hours", g.Sum(r => r.Field<double>("Hours")));
    
                        return row;
                    });
    

    结果将返回IEnumerable&lt;DataRow&gt;,但如果您想返回DataTable,请使用:

    var resultTable = result.CopyToDataTable();
    

    【讨论】:

    • 感谢您的帮助。像魅力一样工作。
    • @Cuong le : 它提供了我准确搜索的内容。非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 2011-01-19
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多