我需要有关过去5年Source
使用情况的统计数据。下面的LINQ查询允许我部分完成工作。
public class Source
{
public int Id { get; set; }
public string Label { get; set; }
}
public class Suite
{
public int Id { get; set; }
public DateTime CreatedTime { get; set; }
public int SourceId { get; set; }
public virtual Source Source { get; set; }
}
var limit = DateTime.Now.AddYears(-5).Year;
var data = _contextProvider.Context.Suites
.GroupBy(x => new { x.CreatedTime.Year, x.SourceId })
.Select(x => new
{
Year = x.Key.Year,
SourceId = x.Key.SourceId,
Count = x.Count()
})
.Where(x => x.Year >= limit)
.OrderByDescending(x => x.Year).ToList();
此LINQ查询的结果如下所示:
现在我需要更进一步:我需要按年使用SourceId
的百分比。
2018年的例子:
正如您在2018年所看到的,共有51个元素(32 + 12 + 7)。这个总数允许我计算一年中每个SourceId的百分比。像这样:
所以我的问题是如何从我的data
对象中获取这些百分比?也许可以直接在我的基本LINQ查询中计算这些百分比?
答案 0 :(得分:0)
你肯定很亲密。我们可以通过分两步来分析您想要的统计数据。
这是所有的最终查询(我对它在SQL中的速度一无所知!)
Suites
.Where(x => x.Created.Year >= 2013)
.GroupBy(x => x.Created.Year)
.Select(x => new {
Total = x.Count(),
Year = x.Key,
Sources = x.GroupBy(i => i.SourceId)
.Select(i => new {
ItemCount = i.Count(),
Source = i.Key })
}).SelectMany(x => x.Sources.Select(s => new {
TotalItems = x.Total,
x.Year,
s.ItemCount,
Percent = (double)s.ItemCount / x.Total,
SourceId = s.Source}))
.OrderBy(x => x.Year)
.ThenBy(x => x.SourceId)
这种方式的工作方式是我们首先按年份分组,因为这是你最外面的分组。
这为2018 - [items]
和2017 - [items]
提供了两组(就我的数据而言)。
然后我们选择了我们的顶级信息,这些信息将是完整的Total
以及Year
。但是,对于单独的行,我们需要进行另一个分组。因此,当我们获取项目列表时,我们应用SourceId进行第二次分组,这将让我们获得给定年份下每个来源的行数。
这给了我们2018年:
2018
2,[Items]
3,[Items]
6,[Items]
然后我们选择这些组中的每一组并将它们展平到关键字中并计算得到以下内容:
2018
SourceId,Count
2,32
3,7
6,12
同样的结构也在2017年重复。
接下来我们想要将其展平,以便我们针对每年生成的每个SourceId / Count重复顶级分组数据。 SelectMany是完美的,因为它需要可枚举的枚举并返回一个扁平的列表。
基本上,我们说每个Year组:选择它下面的所有内容(3-6个不同的SourceId / Count集)并将它们连接成一个列表。
当我们执行此连接步骤时,我们可以将Select
应用于即将出现以获得最终计数的行。
这为我们提供了一组最终数据:
年,总数,计数,百分比,来源
2018,51,32,.627,2
2018,51,7,.137,3
2018,51,12,.235,6
[剪断]
LINQPad中的结果对我来说如下: