LINQ 中的分组?
GroupBy in LINQ?
我正在开发数据库应用程序,它通过标签显示清晰的交易报告。
这是我的数据库。
Title Amount TagsReport (string[] array)
Food 5 "Hotel","Friends"
Food 6 "Hotel"
Family 8 "Hotel","Mobile"
Family 9 "Electricity"
Food 8 "Party"
我希望生成如下报告:
期望输出:
Percentage Title Amount
53% Food 19
Hotel 11
Friends 5
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
我对 LINQ 的了解不够。所以我在寻找完美的解决方案时遇到了很多麻烦。
但是我发现这段代码可以使用,
var ReportingData = ReportListQuery
.Where(Item => Item.Category == "expense")
.GroupBy(item => item.Title)
.Select(itemGroup => new
{
Percentage = Math.Round((itemGroup.Sum(item => item.Amount) / MonthExpense) * 100),
ExpenseTitle = itemGroup.Key,
ExpenseCalculation = itemGroup.Sum(item => item.Amount),
TotalTagAmounts = itemGroup
.SelectMany(item => item.TagsReport.Select(tag => new {
Tag = tag,
Amount = item.Amount
})
.GroupBy(tagAmount => tagAmount.Tag)
.Select(tagAmountGroup => new
{
Tag = tagAmountGroup.Key,
TotalAmount = tagAmountGroup.Sum(tagAmount => tagAmount.Amount)
}))
});
输出就像;
Percentage Title Amount
53% Food 19
Hotel 5
Friends 5
Hotel 6 //Hotel should be grouped here and should with the value 11 :-(
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
但是我的期望输出是:
Percentage Title Amount
53% Food 19
Hotel 11
Friends 5
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
如你所见,一切都是我做的。但不是报告中分组的 'hotel'。我究竟做错了什么?请指教!
在我看来,您的第二个分组依据是按项目完成的,而不是在标签组上完成的。所以,你按标题分组;说,食物。该组现在有三个项目。 "Hotel, Friends" - "Hotel" - "Party"。现在,对于这些组中的每一个,您都在按标签进行分组。那么每个组只有一个。所以你会看到Hotel, Friends, Hotel, Party 是有道理的。在我看来,你不是在对整个集合进行分组,而是对集合中的每个成员进行分组。您可能希望将原始组存储到一个变量中,然后对该数据集的结果求和。当然,只对具有相同标签的项目求和。
我同意 Chris Cummings 关于误用分组的看法。因为您没有展平(即在 TagsReport
字段上调用 SelectMany()
直到您只有一个项目之后,所以对结果进行分组后每个展平序列只有一组。
根据您陈述的期望输出,您似乎真的只是错放了一个右括号。你应该这样写:
var ReportingData = ReportListQuery
.Where(Item => Item.Category == "expense")
.GroupBy(item => item.Title)
.Select(itemGroup => new
{
Percentage = Math.Round((itemGroup.Sum(item => item.Amount) / MonthExpense) * 100),
ExpenseTitle = itemGroup.Key,
ExpenseCalculation = itemGroup.Sum(item => item.Amount),
TotalTagAmounts = itemGroup
.SelectMany(item => item.TagsReport.Select(tag => new
{
Tag = tag,
Amount = item.Amount
})) // add parenthsis here
.GroupBy(tagAmount => tagAmount.Tag)
.Select(tagAmountGroup => new
{
Tag = tagAmountGroup.Key,
TotalAmount = tagAmountGroup.Sum(tagAmount => tagAmount.Amount)
}) // remove parenthesis here
});
换句话说:您希望将每个 "grouped-by-title" 组中的整个展平项目序列分组,而不是展平每个组中的每个单独项目。我只是删除了 next-to-the-last 行上的第二个 )
,并在第二个 GroupBy()
调用之前添加了一个。
这会产生您所描述的输出。这仍然很奇怪(单个标签金额的总和超过了每个标题组的总费用),但至少这是你特别要求的。 :)(好吧,不计算百分比......给定示例数据,没有办法有一个单一的 MonthExpense
百分比相加的值,所以我只是懒得去尝试让那个数字出来对)。
我正在开发数据库应用程序,它通过标签显示清晰的交易报告。
这是我的数据库。
Title Amount TagsReport (string[] array)
Food 5 "Hotel","Friends"
Food 6 "Hotel"
Family 8 "Hotel","Mobile"
Family 9 "Electricity"
Food 8 "Party"
我希望生成如下报告:
期望输出:
Percentage Title Amount
53% Food 19
Hotel 11
Friends 5
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
我对 LINQ 的了解不够。所以我在寻找完美的解决方案时遇到了很多麻烦。
但是我发现这段代码可以使用,
var ReportingData = ReportListQuery
.Where(Item => Item.Category == "expense")
.GroupBy(item => item.Title)
.Select(itemGroup => new
{
Percentage = Math.Round((itemGroup.Sum(item => item.Amount) / MonthExpense) * 100),
ExpenseTitle = itemGroup.Key,
ExpenseCalculation = itemGroup.Sum(item => item.Amount),
TotalTagAmounts = itemGroup
.SelectMany(item => item.TagsReport.Select(tag => new {
Tag = tag,
Amount = item.Amount
})
.GroupBy(tagAmount => tagAmount.Tag)
.Select(tagAmountGroup => new
{
Tag = tagAmountGroup.Key,
TotalAmount = tagAmountGroup.Sum(tagAmount => tagAmount.Amount)
}))
});
输出就像;
Percentage Title Amount
53% Food 19
Hotel 5
Friends 5
Hotel 6 //Hotel should be grouped here and should with the value 11 :-(
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
但是我的期望输出是:
Percentage Title Amount
53% Food 19
Hotel 11
Friends 5
Party 8
57% Family 17
Hotel 8
Mobile 8
Electricity 9
如你所见,一切都是我做的。但不是报告中分组的 'hotel'。我究竟做错了什么?请指教!
在我看来,您的第二个分组依据是按项目完成的,而不是在标签组上完成的。所以,你按标题分组;说,食物。该组现在有三个项目。 "Hotel, Friends" - "Hotel" - "Party"。现在,对于这些组中的每一个,您都在按标签进行分组。那么每个组只有一个。所以你会看到Hotel, Friends, Hotel, Party 是有道理的。在我看来,你不是在对整个集合进行分组,而是对集合中的每个成员进行分组。您可能希望将原始组存储到一个变量中,然后对该数据集的结果求和。当然,只对具有相同标签的项目求和。
我同意 Chris Cummings 关于误用分组的看法。因为您没有展平(即在 TagsReport
字段上调用 SelectMany()
直到您只有一个项目之后,所以对结果进行分组后每个展平序列只有一组。
根据您陈述的期望输出,您似乎真的只是错放了一个右括号。你应该这样写:
var ReportingData = ReportListQuery
.Where(Item => Item.Category == "expense")
.GroupBy(item => item.Title)
.Select(itemGroup => new
{
Percentage = Math.Round((itemGroup.Sum(item => item.Amount) / MonthExpense) * 100),
ExpenseTitle = itemGroup.Key,
ExpenseCalculation = itemGroup.Sum(item => item.Amount),
TotalTagAmounts = itemGroup
.SelectMany(item => item.TagsReport.Select(tag => new
{
Tag = tag,
Amount = item.Amount
})) // add parenthsis here
.GroupBy(tagAmount => tagAmount.Tag)
.Select(tagAmountGroup => new
{
Tag = tagAmountGroup.Key,
TotalAmount = tagAmountGroup.Sum(tagAmount => tagAmount.Amount)
}) // remove parenthesis here
});
换句话说:您希望将每个 "grouped-by-title" 组中的整个展平项目序列分组,而不是展平每个组中的每个单独项目。我只是删除了 next-to-the-last 行上的第二个 )
,并在第二个 GroupBy()
调用之前添加了一个。
这会产生您所描述的输出。这仍然很奇怪(单个标签金额的总和超过了每个标题组的总费用),但至少这是你特别要求的。 :)(好吧,不计算百分比......给定示例数据,没有办法有一个单一的 MonthExpense
百分比相加的值,所以我只是懒得去尝试让那个数字出来对)。