Linq通过C#进行联接,求和和分组

时间:2019-09-24 02:42:23

标签: c# linq join group-by sum

我有以下两个表: 表01:收入。

Id  |  Amount |  Date       | UserId
1   |  50000  | 2019-01-10  |   1
1   |  10000  | 2019-01-15  |   1
1   |  15000  | 2019-02-16  |   1
1   |  20000  | 2019-03-01  |   1

表02:费用。

Id  |  Amount |  Date       | UserId
1   |  10000  | 2019-03-24  |   1
1   |   5000  | 2019-03-24  |   1
1   |  30000  | 2019-04-24  |   1
1   |  20000  | 2019-05-24  |   1

我想把每月的收入和支出加在一起。 其实我想要的结果是这样的(基于上表):

Month  |  Income  |  Expenses
   01  |  60000   |     0
   02  |  15000   |     0
   03  |  20000   |   15000
   04  |    0     |   30000
   05  |    0     |   20000

到目前为止,我已经尝试过:

var incomes = await _context.Incomes.Where(i => i.Date.Year == year && i.UserId == id && i.IsApproved).ToListAsync();
var expenses = await _context.Expenses.Where(e => e.Date.Year == year && e.UserId == id && e.IsApproved).ToListAsync();

var yearlyIncomes = incomes.GroupBy(
            i => i.Date.Month, 
            i => i.Amount,
            (month, income) => new { Month = month, Income = income.Sum() }).OrderBy(i => i.Month).ToList();

var yearlyExpenses = expenses.GroupBy(
            e => e.Date.Month, 
            e => e.Amount,
            (month, expense) => new { Month = month, Expense = expense.Sum() }).OrderBy(e => e.Month).ToList();

这样,我可以分别获得每月的收入和支出。

我也尝试过:

var yearlyIncomes = incomes.GroupBy(x => x.Date.Month)
                        .Select(x => new
                        {
                            Month = x.Key,
                            Income = x.Sum(p => p.Amount),
                            Expense = expenses.Where(c => x.Any(p => p.Date.Month == c.Date.Month)).Sum(c => c.Amount)
                        }).ToList();

有什么方法可以通过一个查询获得所需的结果。

谢谢。

2 个答案:

答案 0 :(得分:0)

您希望在调用ToListAsync()方法实现它们之前合并所有数据并将它们分组。

var incomes = _context
    .Incomes
    .Where(i => i.Date.Year == year && i.UserId == id && i.IsApproved)
    .Select(i => new { Month = i.Date.Month, Income = i.Amount, Expense = 0 });

var expenses = _context
    .Expenses
    .Where(e => e.Date.Year == year && e.UserId == id && e.IsApproved)
    .Select(e => new { Month = e.Date.Month, Income = 0, Expense = e.Amount });

var summary = await incomes
    .Concat(expenses)
    .GroupBy(s => s.Month)
    .Select(g => new { Month = g.Key, Incomes = g.Sum(x => x.Income), Expenses = g.Sum(x => x.Expense) })
    .ToListAsync();

答案 1 :(得分:0)

如果您不想按UserId进行分组,可以尝试一下,但是可以很长

var groupedIncome = incomes
                 .GroupBy(inc => inc.Date.Month) //group it by month
                 .Select(groupedIncomeByMonth => 
                     new { 
                         Month = groupedIncomeByMonth.Key, 
                         Amount = groupedIncomeByMonth
                                      .Sum(monthIncome => monthIncome.Amount), 
                         IsIncome = true}).ToList(); // Marker for Concat/Union All

var groupedExpenses = expenses
                    .GroupBy(exp => exp.Date.Month)
                    .Select(groupedExpenseByMonth => 
                        new { 
                            Month = groupedExpenseByMonth.Key, 
                            Amount = groupedExpenseByMonth
                                         .Sum(monthExpense => monthExpense.Amount), 
                            IsIncome = false }).ToList(); // marker for Concat/Union All

var result = groupedIncome.Concat(groupedExpenses)
                  .GroupBy(x => x.Month)
                  .Select(r => 
                               new { 
                                       Month = r.Key, 
                                       Income = r.Where(p => p.IsIncome).Sum(g => g.Amount), 
                                       Expense = r.Where(p => !p.IsIncome).Sum(g => g.Amount)
                                   }).ToListAsync();