linq сумма нескольких значений

#linq #sum

#linq #сумма

Вопрос:

мне нужно получить сумму оплачиваемых и не оплачиваемых часов.

это мой код.

 var currentMonth = 10;

var userQuery =
            from timeEntry in TimeEntries
            join ta in Tasks on timeEntry.TaskID equals ta.TaskID
            where timeEntry.DateEntity.Month == currentMonth amp;amp; timeEntry.DateEntity.Year == DateTime.Today.Year
            select new
            {
                HoursEntered = timeEntry.HoursEntered,
                Billable = ta.Billable
            };

            var localrows = userQuery.ToList();
            var grouping = localrows.GroupBy(x => x.Billable);

            var userList = grouping.Select(q => new 
            {
                billableHours = q.Where(x=> x.Billable == true),
                nonBillableHours = q.Where(x=> x.Billable != true)
            });
  

кажется, я не могу найти способ получить сумму.
Мне нужна сумма этих двух столбцов, чтобы я мог их вызывать
и вычислять значения, которые я получаю от них.

Ответ №1:

Когда вам нужно более одного агрегата, вы все равно можете получить результат с помощью одного запроса, используя метод group by constant . Который в данном конкретном случае может быть объединен с условным Sum :

 var hoursInfo =
    (from timeEntry in TimeEntries
     join ta in Tasks on timeEntry.TaskID equals ta.TaskID
     where timeEntry.DateEntity.Month == currentMonth amp;amp; timeEntry.DateEntity.Year == DateTime.Today.Year
     group new { timeEntry.HoursEntered, ta.Billable } by 1 into g
     select new
     {
         BillableHours = g.Sum(e => e.Billable ? e.HoursEntered : 0),
         NonBillableHours = g.Sum(e => !e.Billable ? e.HoursEntered : 0),
     }).FirstOrDefault();
  

Ответ №2:

Вам не нужно группировать их. Попробуйте выполнить этот запрос:

 var userQuery =
    from timeEntry in TimeEntries
    join ta in Tasks on timeEntry.TaskID equals ta.TaskID
    where timeEntry.DateEntity.Month == currentMonth 
        amp;amp; timeEntry.DateEntity.Year == DateTime.Today.Year
    select new
    {
        HoursEntered = timeEntry.HoursEntered,
        Billable = ta.Billable
    };

var billableHours = userQuery
    .Where(m => m.Billable) // Billable
    .Select(m => m.HoursEntered)
    .DefaultIfEmpty(0)
    .Sum();

var nonBillableHours  = userQuery
    .Where(m => !m.Billable) // Non-bilable
    .Select(m => m.HoursEntered)
    .DefaultIfEmpty(0)
    .Sum();
  

Комментарии:

1. отлично работает. хотя defaultifempty , возвращает ошибку перегрузки, не поддерживаемую в linqpad.

2. Я рад, что это помогло. Что такое тип HoursEntered ?

3. это двойное значение.

4. @andrelange91, попробуйте использовать like DefaultIfEmpty() без параметров. Пожалуйста, дайте мне знать результат

5. @andrelange91, я не знаком с linqpad , поэтому не могу помочь. В этом нет необходимости, но рекомендуется использовать его, потому что, когда ваш запрос не вернет какой Sum -либо метод данных, он выдаст исключение.

Ответ №3:

 var currentMonth = 10;
        var TimeEntries = new List<TimeEntry>() { 
        new TimeEntry(){TaskID = 1,DateEntity = DateTime.Now.AddDays(1),HoursEntered =2},
        new TimeEntry(){TaskID = 2,DateEntity = DateTime.Now.AddDays(2),HoursEntered =3},
        new TimeEntry(){TaskID = 3,DateEntity = DateTime.Now.AddDays(3),HoursEntered =2},
        new TimeEntry(){TaskID = 4,DateEntity = DateTime.Now.AddDays(4),HoursEntered =4},
        new TimeEntry(){TaskID = 5,DateEntity = DateTime.Now.AddDays(5),HoursEntered =2},
        new TimeEntry(){TaskID = 6,DateEntity = DateTime.Now.AddDays(6),HoursEntered =6}
        };

        var UserTasks = new List<UserTask>(){
               new UserTask(){TaskID = 1,Billable = true} ,
               new UserTask(){TaskID = 2,Billable = false} ,
               new UserTask(){TaskID = 3,Billable = true} ,
               new UserTask(){TaskID = 4,Billable = false} ,
               new UserTask(){TaskID = 5,Billable = true} ,
               new UserTask(){TaskID = 6,Billable = false} 
        };

        var userQuery =
                    from x in
                        (from timeEntry in TimeEntries
                         join ta in UserTasks on timeEntry.TaskID equals ta.TaskID
                         where timeEntry.DateEntity.Month == currentMonth amp;amp; timeEntry.DateEntity.Year == DateTime.Today.Year
                         select new
                         {
                             HoursEntered = timeEntry.HoursEntered,
                             Billable = ta.Billable
                         })
                    group x by x.Billable into g
                    select new
                    {
                        IsBillable = g.Key,
                        Billabe = g.Where(t => t.Billable == true).Sum(x => x.HoursEntered),
                        NonBillable = g.Where(t => t.Billable == false).Sum(x => x.HoursEntered)
                    };

        foreach (var item in userQuery.ToList())
        {
            Console.WriteLine(string.Format("{0} - {1}", item.IsBillable? "Billable":"Non-Billable",item.IsBillable?item.Billabe:item.NonBillable));

        }