如何在 Linq 中将行转换为列
How to convert Row to Columns in Linq
我有 table ReportData 有以下记录
Agency
Year
Month
MonthCount
One
2017
Jan
4
One
2017
Feb
6
One
2017
Nov
29
One
2017
Dec
38
One
2018
Jan
20
One
2019
Feb
18
Two
2017
Jan
24
Two
2017
Feb
66
Three
2017
Nov
9
Four
2017
Dec
8
Four
2018
Jan
22
Four
2019
Feb
48
如何转换成下面的table?请让我知道 Linq 声明。提前感谢您的帮助。
Agency
Month
2017
2018
2019
One
Jan
4
20
0
One
Feb
6
0
18
One
Nov
29
0
0
One
Dec
38
0
0
Two
Jan
24
0
0
Two
Feb
66
0
0
Three
Nov
9
0
0
Four
Jan
0
22
0
Four
Feb
0
0
48
Four
Dec
8
0
0
来源class结构
public class ReportingData
{
public string AgencyName { get; set; }
public int Year { get; set; }
public string MonthNumnber { get; set; }
public string Month { get; set; }
public int MonthCount { get; set; }
}
在我看来,每个 [Agency, Month] 组合,您需要 2017..2019 年的 MonthCounts。
不知道你想要几年后的:只有最近三年?还是 2017.. 2025 年?不过那是后面的问题了。
我的建议是制作具有相同 [Agency, Month] 组合值的 ReportData 组。使用
overload of Enumerable.GroupBy that has a parameter resultSelector
精确定义结果。如果您的数据在不同的进程中(通常是数据库),请使用 IQueryable 版本。
IEnumerable<Report> reportData = ...
// make groups with same values for [Agency, Month] combination
var result = reportData.GroupBy(report => new
{
Agency = report.Agency,
Month = report.Month,
},
// parameter resultSelector: for every [Agency, Month] combination,
// and all reports that have this [Agency, Month] combination,
// make one new:
(agencyMonthCombination, reports] => new
{
Agency = agencyMonthCombination.Agency,
Month = agencyMonthCombination.Month,
Year2017 = reports.Where(report => report.Year == 2017)
.Select(report => report.MonthCount)
.Sum();
Year2018 = reports.Where(report => report.Year == 2018)
.Select(report => report.MonthCount)
.Sum();
Year2019 = reports.Where(report => report.Year == 2018)
.Select(report => report.MonthCount)
.Sum();
如果您希望每年只有一份报告,则不必求和,只需使用 FirstOrDefault 即可。
你看到了这种命名年份 2017..2019 的方法的缺点。如果你为所有年份或过去 N 年编写代码,代码会容易得多:
// parameter resultSelector
(agencyMonthCombination, reports] => new
{
Agency = agencyMonthCombination.Agency,
Month = agencyMonthCombination.Month,
// group the reports with this [Agency, Month] combination in years
MonthCounts = reports.GroupBy(report => report.Year,
(year, reportsInThisYear) => new
{
Year = year,
MonthCount = reportsInThisYear.Select(report => report.MonthCount).Sum(),
})
// if you only want the last N: orderby descending Year and Take(N)
.OrderByDescending(yearMonthCount => yearMonthCount.Year)
.Take(N)
.ToList(),
});
我有 table ReportData 有以下记录
Agency | Year | Month | MonthCount |
---|---|---|---|
One | 2017 | Jan | 4 |
One | 2017 | Feb | 6 |
One | 2017 | Nov | 29 |
One | 2017 | Dec | 38 |
One | 2018 | Jan | 20 |
One | 2019 | Feb | 18 |
Two | 2017 | Jan | 24 |
Two | 2017 | Feb | 66 |
Three | 2017 | Nov | 9 |
Four | 2017 | Dec | 8 |
Four | 2018 | Jan | 22 |
Four | 2019 | Feb | 48 |
如何转换成下面的table?请让我知道 Linq 声明。提前感谢您的帮助。
Agency | Month | 2017 | 2018 | 2019 |
---|---|---|---|---|
One | Jan | 4 | 20 | 0 |
One | Feb | 6 | 0 | 18 |
One | Nov | 29 | 0 | 0 |
One | Dec | 38 | 0 | 0 |
Two | Jan | 24 | 0 | 0 |
Two | Feb | 66 | 0 | 0 |
Three | Nov | 9 | 0 | 0 |
Four | Jan | 0 | 22 | 0 |
Four | Feb | 0 | 0 | 48 |
Four | Dec | 8 | 0 | 0 |
来源class结构
public class ReportingData
{
public string AgencyName { get; set; }
public int Year { get; set; }
public string MonthNumnber { get; set; }
public string Month { get; set; }
public int MonthCount { get; set; }
}
在我看来,每个 [Agency, Month] 组合,您需要 2017..2019 年的 MonthCounts。
不知道你想要几年后的:只有最近三年?还是 2017.. 2025 年?不过那是后面的问题了。
我的建议是制作具有相同 [Agency, Month] 组合值的 ReportData 组。使用 overload of Enumerable.GroupBy that has a parameter resultSelector 精确定义结果。如果您的数据在不同的进程中(通常是数据库),请使用 IQueryable 版本。
IEnumerable<Report> reportData = ...
// make groups with same values for [Agency, Month] combination
var result = reportData.GroupBy(report => new
{
Agency = report.Agency,
Month = report.Month,
},
// parameter resultSelector: for every [Agency, Month] combination,
// and all reports that have this [Agency, Month] combination,
// make one new:
(agencyMonthCombination, reports] => new
{
Agency = agencyMonthCombination.Agency,
Month = agencyMonthCombination.Month,
Year2017 = reports.Where(report => report.Year == 2017)
.Select(report => report.MonthCount)
.Sum();
Year2018 = reports.Where(report => report.Year == 2018)
.Select(report => report.MonthCount)
.Sum();
Year2019 = reports.Where(report => report.Year == 2018)
.Select(report => report.MonthCount)
.Sum();
如果您希望每年只有一份报告,则不必求和,只需使用 FirstOrDefault 即可。
你看到了这种命名年份 2017..2019 的方法的缺点。如果你为所有年份或过去 N 年编写代码,代码会容易得多:
// parameter resultSelector
(agencyMonthCombination, reports] => new
{
Agency = agencyMonthCombination.Agency,
Month = agencyMonthCombination.Month,
// group the reports with this [Agency, Month] combination in years
MonthCounts = reports.GroupBy(report => report.Year,
(year, reportsInThisYear) => new
{
Year = year,
MonthCount = reportsInThisYear.Select(report => report.MonthCount).Sum(),
})
// if you only want the last N: orderby descending Year and Take(N)
.OrderByDescending(yearMonthCount => yearMonthCount.Year)
.Take(N)
.ToList(),
});