如何在 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(),
    });