简体   繁体   English

c#数据表,使用compute计算行范围内的平均值

[英]c# datatable using compute to calculate an average on a range of rows

I am trying to use .Compute on a datatable whereby it only calculates an average on a set of rows. 我试图在数据表上使用.Compute,从而仅计算一组行的平均值。 I have looked through the Microsoft docs and searched for a while and cannot find where a filter works against the datatable structure. 我浏览了Microsoft文档并搜索了一段时间,但找不到针对数据表结构的过滤器。 Looking for something like: - 寻找类似的东西:-

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

It works when using an empty filter but calculates on all of the data. 使用空过滤器时它可以工作,但可以计算所有数据。

If this is not possible, I am considering using a loop and sum to calculate the average after. 如果无法做到这一点,我正在考虑使用循环和求和后计算平均值。

EDIT: I am looking at sample of data at a point in time and averaging a range either side of this (eg being the 20th interval and rows 17 - 22) 编辑:我正在查看某个时间点的数据样本,并平均每个范围的范围(例如,第20个间隔和第17-22行)

The error message is $exception {"Cannot find column [Rows]."} - System.Data.EvaluateException 错误消息是$ exception {“找不到列[行]。”}-System.Data.EvaluateException

Sample data (limited to first 30 rows): 样本数据(仅限于前30行):

Price 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 价格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,6800.6,600.600,6800.6600.600 ,6250.700,6213.500,6207.000,6184.200,6333.200

Here is my solution using a loop 这是我使用循环的解决方案

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

You won't be able to do this the way you're approaching it. 您将无法以接近它的方式进行操作。

To use the .Compute method, you need to pass a column name in the filter expression - as it is a normal WHERE clause. 要使用.Compute方法,您需要在过滤器表达式中传递列名-因为它是正常的WHERE子句。 At a T-SQL level you can utilize the ROW_NUMBER function to enumerate the returned rows in a new column - say Index - then apply the filter on that enumerated column. 在T-SQL级别,您可以利用ROW_NUMBER函数枚举新列中返回的行(例如, 索引) ,然后将过滤器应用于该枚举列。 Eg, 例如,

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

Another approach would be to do this with the aid of LINQ and leave the T-SQL query as is: 另一种方法是借助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()
;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM