【问题标题】:c# datatable using compute to calculate an average on a range of rowsc# datatable 使用计算计算一系列行的平均值
【发布时间】:2019-09-14 08:02:45
【问题描述】:

我正在尝试在数据表上使用 .Compute,它只计算一组行的平均值。我查看了 Microsoft 文档并搜索了一段时间,但找不到过滤器对数据表结构起作用的位置。寻找类似的东西:-

string connectStatement = "SELECT Price FROM PData WHERE Code = '" + this.ItemCode + "' ORDER BY TradeDate DESC OFFSET 0 ROWS FETCH NEXT 300 ROWS ONLY";
DataTable itemsDT = ConnectionManager.GetTable(connectStatement);
Records20 = (decimal)itemsDT.Compute("Avg(Price)", "Rows > 16 AND Rows < 23");

它在使用空过滤器时有效,但会根据所有数据进行计算。

如果这是不可能的,我正在考虑使用循环和求和来计算平均值。

编辑:我正在查看某个时间点的数据样本,并将其任一侧的范围取平均值(例如,第 20 个区间和第 17 - 22 行)

错误信息是 $exception {"找不到列 [Rows]。"} - System.Data.EvaluateException

样本数据(限于前 30 行):

价格 6464.100, 6426.800, 6406.100, 6349.300, 6329.600, 6295.500, 6247.900, 6189.100, 6206.100, 6214.600, 6231.000, 6130.200, 6115.700, 6129.500, 6097.300, 6159.600, 6149.700, 6118.400, 6156.700, 6118.800, 6054.700, 6014.700, 6198.000, 6242.800, 6272.900, 6250.700, 6213.500, 6207.000, 6184.200, 6333.200

【问题讨论】:

  • 您收到什么错误信息?您的数据结构是什么,请您添加一些示例数据。
  • 嗨,彼得。我刚刚按要求更新了信息。如上所述,如果无法在 .Compute 函数中过滤,我将使用循环并从那里计算平均值。感谢您的关注...
  • 它将Rows解释为字段名;指定行数的查询将不起作用。我不熟悉Compute,但我不认为你可以那样使用它。
  • 简单的 WHERE : itemsDT.AsEnumerable().Where((x,index) => (index > 16) && (index

标签: c# datatable average


【解决方案1】:

你将无法以你接近它的方式做到这一点。

要使用.Compute 方法,您需要在过滤器表达式中传递一个列名——因为它是一个普通的WHERE 子句。在 T-SQL 级别,您可以利用 ROW_NUMBER 函数在新列中枚举返回的行 - 例如 Index - 然后在该枚举列上应用过滤器。例如,

string connectStatement = "SELECT ROW_NUMBER() OVER(ORDER BY TradeDate DESC) AS Index, Price FROM PData WHERE Code = '" + this.ItemCode + "' OFFSET 0 ROWS FETCH NEXT 300 ROWS ONLY";
DataTable itemsDT = ConnectionManager.GetTable(connectStatement);
Records20 = (decimal)itemsDT.Compute("Avg(Price)", "Index > 16 AND Index < 23");

另一种方法是在 LINQ 的帮助下执行此操作,并保持 T-SQL 查询不变:

string connect statement = "SELECT Price FROM PData WHERE Code = '" + this.ItemCode + "' ORDER BY TradeDate DESC OFFSET 0 ROWS FETCH NEXT 300 ROWS ONLY";
Records20 = itemsDT.AsEnumerable() // this will yeald a IEnumerable<DataRow>
    .Skip(16)
    .Take(7)
    .Select(dr => (decimal)dr["Price"])
    .Average()
;

【讨论】:

  • 您好,博日达尔。谢谢您的回答。我确实在其他地方找到了第一个建议,但是当我及时查看几个数据点时,我认为这不会有效,因此将 300 条记录加载到数据表中。感谢您提供第二个解决方案。
  • 仅供参考,ROW_NUMBER 不要为您现有的查询增加开销。 DB 引擎足够智能,可以将枚举优化为仅需要的记录。我认为排序是这里的关键性能问题,即使没有ROW_NUMBER,它也是如此。所以别担心,至少试一试。此外,如果您负担得起,请在 T-SQL 查询中进行过滤。这样过滤是在数据库服务器上完成的,只有有用的数据通过网络。 LINQ 解决方案适用于已加载到 RAM 中的数据。
【解决方案2】:

这是我使用循环的解决方案

decimal sumCalculation = 0;
for (int record = 17; record < 23; record++)
{
     sumCalculation += decimal.Parse(itemsDT.Rows[record]["Price"].ToString());
}
Records20 = sumCalculation / 6;

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2019-04-03
    • 1970-01-01
    • 2011-05-17
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    相关资源
    最近更新 更多