从我的 LINQ 查询中计算百分比(按年)
Computing percentages (by year) from my LINQ query
我需要有关 Source
最近 5 年使用情况的统计数据。下面的 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 的百分比。像这样:
- { 年份 = 2018,SourceId = 2,百分比 = 63 }
- { 年份 = 2018,SourceId = 6,百分比 = 23 }
- { 年份 = 2018,SourceId = 3,百分比 = 14 }
所以我的问题是如何从我的 data
对象中获取这些百分比?也许可以直接在我的基本 LINQ 查询中计算这些百分比?
你肯定很接近。我们可以通过将分组依据分为两步来获得您想要的统计数据。
这是所有的最终查询(我不保证它在 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]
的两组(就我的数据而言)。
然后我们 select 得出我们的顶级信息,这将是完整的 Total
以及 Year
。然而,对于单独的行,我们需要进行另一个分组。因此,当我们获取项目列表时,我们将按 SourceId 应用第二个分组,这将使我们获得给定年份下每个来源的行数。
这给了我们 2018 年:
2018
2, [Items]
3, [Items]
6, [Items]
然后我们对这些组中的每一个进行 Select 并将它们展平到键和计数中,这给了我们以下内容:
2018
SourceId, Count
2, 32
3, 7
6, 12
同样的结构也在 2017 年重复。
接下来我们要将其展平,以便我们对每年生成的每个 SourceId/Count 重复顶级分组数据。 SelectMany 非常适合这个,因为它需要可枚举的可枚举和 returns 一个单一的扁平化列表。
基本上,我们说对于每个年级组:Select 它下面的所有内容(3-6 个不同的 SourceId/Count 组)并将它们全部连接成一个列表。
当我们执行此连接步骤时,我们可以将 Select
应用于即将出现的行以获得最终计数。
这为我们提供了一组最终数据,如下所示:
Year, Total, Count, Percent, SourceId
2018, 51, 32, .627, 2
2018, 51, 7, .137, 3
2018, 51, 12, .235, 6
[Snip]
我在 LINQPad 中的结果如下所示:
我需要有关 Source
最近 5 年使用情况的统计数据。下面的 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 的百分比。像这样:
- { 年份 = 2018,SourceId = 2,百分比 = 63 }
- { 年份 = 2018,SourceId = 6,百分比 = 23 }
- { 年份 = 2018,SourceId = 3,百分比 = 14 }
所以我的问题是如何从我的 data
对象中获取这些百分比?也许可以直接在我的基本 LINQ 查询中计算这些百分比?
你肯定很接近。我们可以通过将分组依据分为两步来获得您想要的统计数据。
这是所有的最终查询(我不保证它在 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]
的两组(就我的数据而言)。
然后我们 select 得出我们的顶级信息,这将是完整的 Total
以及 Year
。然而,对于单独的行,我们需要进行另一个分组。因此,当我们获取项目列表时,我们将按 SourceId 应用第二个分组,这将使我们获得给定年份下每个来源的行数。
这给了我们 2018 年:
2018
2, [Items]
3, [Items]
6, [Items]
然后我们对这些组中的每一个进行 Select 并将它们展平到键和计数中,这给了我们以下内容:
2018
SourceId, Count
2, 32
3, 7
6, 12
同样的结构也在 2017 年重复。
接下来我们要将其展平,以便我们对每年生成的每个 SourceId/Count 重复顶级分组数据。 SelectMany 非常适合这个,因为它需要可枚举的可枚举和 returns 一个单一的扁平化列表。
基本上,我们说对于每个年级组:Select 它下面的所有内容(3-6 个不同的 SourceId/Count 组)并将它们全部连接成一个列表。
当我们执行此连接步骤时,我们可以将 Select
应用于即将出现的行以获得最终计数。
这为我们提供了一组最终数据,如下所示:
Year, Total, Count, Percent, SourceId
2018, 51, 32, .627, 2
2018, 51, 7, .137, 3
2018, 51, 12, .235, 6
[Snip]
我在 LINQPad 中的结果如下所示: