简体   繁体   English

使用 LINQ 将数据列表聚合并分组到新列表中,但 Sum 为 0

[英]Using LINQ to aggregate and group a list of data into a new list but Sum is 0

I have a list of data retrieved from SQL and stored in a class.我有一个从 SQL 检索并存储在 class 中的数据列表。 I want to now aggregate the data using LINQ in C# rather than querying the database again on a different dataset.我现在想在 C# 中使用 LINQ 聚合数据,而不是在不同的数据集上再次查询数据库。

在此处输入图像描述

Example data I have is above.我的示例数据在上面。 Date, Period, Price, Vol and I am trying to create a histogram using this data.日期、期间、价格、成交量,我正在尝试使用这些数据创建直方图。 I tried to use Linq code below but seem to be getting a 0 sum.我尝试使用下面的 Linq 代码,但似乎总和为 0。

  1. Period needs to be a where clause based on a variable Period 需要是一个基于变量的 where 子句
  2. Volume needs to be aggregated for the price ranges需要针对价格范围汇总交易量
  3. Price needs to be a bucket and grouped on this column价格需要是一个桶并在此列上分组

I dont want a range.我不想要一个范围。 Just a number for each bucket.每个桶只有一个数字。

Example output I want is (not real data just as example):我想要的示例 output 是(不是真实数据,仅作为示例):

Bucket    SumVol
18000       50
18100       30
18200       20

Attempted the following LINQ query but my SUM seems to be be empty.尝试了以下 LINQ 查询,但我的 SUM 似乎为空。 I still need to add my where clause in, but for some reason the data is not aggregating.我仍然需要添加我的 where 子句,但由于某种原因,数据没有聚合。

var ranges = new[] { 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 20000 };
var priceGroups = eod.GroupBy(x => ranges.FirstOrDefault(r => r > x.price))
    .Select(g => new { Price = g.Key, Sum = g.Sum(s => s.vol)})
    .ToList();

var grouped = ranges.Select(r => new
{
    Price = r,
    Sum = priceGroups.Where(g => g.Price > r || g.Price == 0).Sum(g => g.Sum)
});

Use LINQ instead to query the DB is great, mainly because you are saving process avoiding a new call to your DB.使用 LINQ 代替查询数据库很棒,主要是因为您正在保存过程,避免对数据库的新调用。 And in case you don't have a high update BD (that change the data very quickly) you can use the retrived data to calculate all using LINQ如果您没有高更新 BD(非常快速地更改数据),您可以使用检索到的数据来计算所有使用 LINQ

First things first... There seems to be nothing wrong with your priceGroups list.首先要做的事情...您的priceGroups列表似乎没有任何问题。 I've run that on my end and, as far as I can understand your purpose, it seems to be grabbing the expected values from your dataset.我已经运行了它,据我所知你的目的,它似乎是从你的数据集中获取预期值。

var ranges = new[] { 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 20000 };
var priceGroups = eod.GroupBy(x => ranges.FirstOrDefault(r => r > x.price))
      .Select(g => new { Price = g.Key, Sum = g.Sum(s => s.vol) })
      .ToList();

Now, I assume your intent with the grouped list was to obtain yet another anonymous type list, much like you did with your priceGroups list, which is also an anonymous type list... List<'a> in C#.现在,我假设您对分组列表的意图是获取另一个匿名类型列表,就像您对priceGroups列表所做的那样,这也是一个匿名类型列表... C# 中的 List<'a>。

var grouped = ranges.Select(r => new
{
    Price = r,
    Sum = priceGroups.Where(g => g.Price > r || g.Price == 0).Sum(g => g.Sum)
});

For starters, your are missing the ToList() method call at the end of it.对于初学者,您在其末尾缺少ToList()方法调用。 However, that's not the main issue here, as you could still work with an IEnumerable<'a> just as well for most purposes.但是,这不是这里的主要问题,因为对于大多数用途,您仍然可以使用 IEnumerable<'a>。

As I see it, the core problem is at your anonymous property Sum attribution.在我看来,核心问题在于您的匿名属性Sum归属。 Why are your filtering for g.Price > r || g.Price == 0为什么要过滤g.Price > r || g.Price == 0 g.Price > r || g.Price == 0 ? g. g.Price > r || g.Price == 0

There is no element with Price equal to zero on your priceGroups list.您的priceGroups列表中没有价格为零的元素。 Those are a subset of ranges , and there is no zero there.这些是range的一个子集,并且那里没有零。 Then you are comparing every value in ranges against that subset in priceGroups , and consolidating the Sums of every element in priceGroups that have Price higher than the range being evaluated.然后,您将范围中的每个值与priceGroups中的该子集进行比较,并合并priceGroups价格高于所评估范围的每个元素的总和 In other words, the property Sum in your grouped list is a sum of sums.换句话说,分组列表中的属性Sum是总和的总和。

Keep in mind that priceGroups is already an aggregated list.请记住, priceGroups已经是一个聚合列表。 It seems to me you are trying to aggregate it again when you call the Sum() method after a Where() clause like you are doing.在我看来,当您像您正在做的那样在 Where()子句之后调用Sum()方法时,您正在尝试再次聚合它。 That doesn't make much sense.这没有多大意义。

What you want (I believe) for the Sum property in the grouped list is for it to be the same as the Sum property in the priceGroups list, if the range being evaluated matches the Price being evaluated.如果正在评估的范围与正在评估的价格相匹配,那么您希望(我相信)分组列表中的Sum属性与priceGroups列表中的Sum属性相同。 Furthermore, where there is no matches, you want your grouped list Sum to be zero, as that means the range being evaluated was not in the original dataset.此外,如果没有匹配项,您希望分组列表Sum为零,因为这意味着正在评估的范围不在原始数据集中。 You can achieve that with the following instead:您可以通过以下方式实现:

Sum = priceGroups.FirstOrDefault(g => g.Price == r)?.Sum ?? 0

You said your Sum was "empty" in your post, but that's not the behavior I saw on my end.你说你的总和在你的帖子中是“空的”,但这不是我看到的行为。 Try the above and, if still not behaving as you would expect, share a small dataset for which you know the expected output with me and I can try to help you further.尝试上述方法,如果仍然没有达到您的预期,请与我分享一个您知道预期 output 的小数据集,我可以尝试进一步帮助您。

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

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