Как мне посчитать столбец bools, сгруппированный по дате в LINQ? - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть таблица, которая содержит 15 сеансов бронирования по датам. В каждой строке указана запись о людях в сеансах, которые они посещают.

Для каждой даты мне нужно сосчитать bools для каждой сессии S1, S2 и т. Д.

Сколько в S1 на 01.01.2009?

Вот таблица в ядре asp.net

! [Рис. Таблицы] [https://imgur.com/a/SguJmLI]

Это выглядит так

Session   S1  S2  S3  S4  S5  S6  S7
1/1/2019   1  0    1   1   1   0   1
1/1/2019   0  1    1   1   1   1   1
2/1/2019   0  0    1   1   1   1   1
2/1/2019   0  1    1   1   1   1   1

Есть несколько сессий, и мне нужно получить итоговый подсчет bools для каждой даты.

1/1/2019   1  1    2   2   2   1   2
2/1/2019   0  1    2   2   2   2   2

К сожалению, у меня нет ни одной вещи для генерации

Но вот как я генерирую сетку

 return View(await _context.SeatBooking
           .OrderByDescending(s => s.SeatDate)
           .ToListAsync());

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Поскольку тип столбцов bool, первым делом необходимо преобразовать bool в int.

Func<bool, int> convertBoolToInt = flag => flag ? 1 : 0;

var query = _context.SeatBooking
    .Select(s => new SeatBookingDto
    {
        SeatDate = s.SeatDate,
        S1 = convertBoolToInt(s.S1),
        S2 = convertBoolToInt(s.S2),
        S3 = convertBoolToInt(s.S3),
        S4 = convertBoolToInt(s.S4),
        S5 = convertBoolToInt(s.S5),
        S6 = convertBoolToInt(s.S6),
        S7 = convertBoolToInt(s.S7),
    });

И теперь мы можем сгруппировать и вычислить сумму каждого столбца для каждой группы:

query.GroupBy(m => m.SeatDate, m => m, (k, g) => new
{
    Date = k,
    S1= g.Sum(m=>m.S1),
    S2= g.Sum(m=>m.S2),
    S3= g.Sum(m=>m.S3),
    S4= g.Sum(m=>m.S4),
    S5= g.Sum(m=>m.S5),
    S6= g.Sum(m=>m.S6),
    S7= g.Sum(m=>m.S7),
})

Если вы используете EFCore, соответствующий запрос и результат:

App>       SELECT [s].[SeatDate], [s].[S1], [s].[S2], [s].[S3], [s].[S4], [s].[S5], [s].[S6], [s].[S7]
App>       FROM [SeatBooking] AS [s]
App>       ORDER BY [s].[SeatDate]
App> 1/1/2019 12:00:00 AM : 1,1,2,2,2,1,2
App> 2/1/2019 12:00:00 AM : 0,1,2,2,2,2,2

Обратите внимание, что выражение LINQ g.sum() здесь все оценивается локально, что означает, что не оценивается базой данных.Похоже, что EFcore не эволюционировал, чтобы иметь возможность переводить выражение Aggregate (например, Sum) в запрос SQL, который может быть выполнен на сервере.

Если вы хотите запрашивать объекты только в памятиесть еще один способ сделать это (пока не поддерживается EFCore):

query.GroupBy(m=>m.SeatDate,m=>m,(k,g)=>new {
    Date = k,
    Count = g.Aggregate((c,n)=>new SeatBookingDto{
        SeatDate=c.SeatDate,
        S1=c.S1+n.S1,
        S2=c.S2+n.S2,
        S3=c.S3+n.S3,
        S4=c.S4+n.S4,
        S5=c.S5+n.S5,
        S6=c.S6+n.S6,
        S7=c.S7+n.S7,
    }) 
})
0 голосов
/ 12 сентября 2018

Спасибо, ребята, просто быстрое обновление, мне кажется, это работает, но неуклюже

  ViewData["CountSessions"] = _context.SeatBooking
                    //  .Where(s => s.StudentEmail == _userManager.GetUserId(User))
                    .GroupBy(d => d.SeatDate)
                    .Select(s => new
                    {
                        SumS1 = s.Count(c => c.S1 == true),
                        SumS2 = s.Count(c => c.S2 == true),
                        SumS3 = s.Count(c => c.S3 == true),
                        SumS4 = s.Count(c => c.S4 == true),
                        SumS5 = s.Count(c => c.S5 == true),
                        SumS6 = s.Count(c => c.S6 == true),
                        SumS7 = s.Count(c => c.S7 == true),
                        SumS8 = s.Count(c => c.S8 == true),
                        SumS9 = s.Count(c => c.S9 == true),
                        SumS10 = s.Count(c => c.S10 == true)

                    }).ToListAsync();
0 голосов
/ 12 сентября 2018

Я думаю, вы можете попробовать это:

_context.SeatBooking.Select(i => i.Session).Distinct().Select(i =>
        new
        {
            Session = i,
            S1 = _context.SeatBooking.Count(j => j.Session == i && j.S1 == 1),
            S2 = _context.SeatBooking.Count(j => j.Session == i && j.S2 == 1),
        }
).OrderByDescending(s => s.Session).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...