2 Вопрос: Борьба за преобразование SQL-запроса в его эквивалент LINQ - множественные объединения, группировки и агрегатные функции

вопрос создан в Thu, May 2, 2019 12:00 AM

У меня есть следующий запрос, который дает ожидаемые результаты в SQL Server Management Studio:

SELECT 
    u.DisplayName,
    up.ColorPreferences,
    SUM(rt.Score) AS Points,
    COUNT(*) AS Plans,
    MAX(pl.Created) AS MaxDate
FROM 
    [dbo].[Users] u
INNER JOIN 
    [dbo].[PlanLogs] pl ON u.Id = pl.UserId
INNER JOIN 
    [dbo].[ResourceTypes] rt ON pl.ResourceTypeId = rt.Id
INNER JOIN 
    [dbo].[UserProfile] up ON pl.UserId = up.UserId
GROUP BY 
    u.DisplayName, up.ColorPreferences;

у меня есть следующий рабочий запрос linq:

from u in _context.Users
join pl in _context.PlanLogs on u.Id equals pl.UserId
join rt in _context.ResourceTypes on pl.ResourceTypeId equals rt.ID
join up in _context.UserProfile on pl.UserId equals up.UserId
group rt by new { u.DisplayName, up.ColorPreferences} into g
select new
{
DisplayName = g.Key.DisplayName,
ColorPrefs = g.Key.ColorPreferences,
Points = g.Sum(x => x.Score),
Plans = g.Count()
};

Как видите, отсутствует MaxDate. Я не могу получить доступ к MaxDate, потому что g содержит свойства из RT. Я пробовал следующее, и я получаю «Значение не попадает в ожидаемый диапазон»

from u in _context.Users
join pl in _context.PlanLogs on u.Id equals pl.UserId
join rt in _context.ResourceTypes on pl.ResourceTypeId equals rt.ID
join up in _context.UserProfile on pl.UserId equals up.UserId
group new { rt, pl } by new { u.DisplayName, up.ColorPreferences} into g
select new
{
DisplayName = g.Key.DisplayName,
ColorPrefs = g.Key.ColorPreferences,
Points = g.Sum(x => x.rt.Score),
Plans = g.Count()
MaxDate = g.Max(m => m.pl.Created)
};

Как добавить MaxDate к результатам?

Спасибо

    
0
  1. Вторая попытка должна работать. Что это за EF (6, Core, какая версия)? Можем ли мы увидеть трассировку стека исключений?
    2019-05-02 17: 58: 14Z
  2. Я вижу, что вы делаете внутренний join, но возможно ли, что некоторые значения m.pl.Created равны null? Возможно, если вы сделали g.Where(m => m.pl.Created != null).Max(m => m.pl.Created)? Вы получаете предупреждение о том, что Max будет выполняться локально?
    2019-05-02 19: 48: 34Z
2 ответа                              2                         

Вы пытались получить доступ к максимальному значению из pl.created при первом запросе linq? почему вы группируете по RT, а не весь результат? попробуйте это вместо этого:

from u in _context.Users
join pl in _context.PlanLogs on u.Id equals pl.UserId
join rt in _context.ResourceTypes on pl.ResourceTypeId equals rt.ID
join up in _context.UserProfile on pl.UserId equals up.UserId
group u by new { u.DisplayName, up.ColorPreferences} into g
select new
{
  DisplayName = g.Key.DisplayName,
  ColorPrefs = g.Key.ColorPreferences,
  Points = g.Sum(x => x.Score),
  Plans = g.Count(),
  MaxDate = g.Max(m => m.pl.Created)
};
    
0
2019-05-02 15: 36: 58Z
  1. спасибо за ответ, к сожалению, то, что вы предложили, имеет смысл, но является синтетически неверным. Вы не можете просто иметь «группу по новому». Недопустимый термин выражения от
    2019-05-02 15: 29: 01Z
  2. вы пытались группировать по u 'Users' вместо rt?
    2019-05-02 15: 37: 24Z
  3. да, тогда я получаю только перечисленные свойства, которые принадлежат таблице пользователей. Я использовал RT, чтобы иметь возможность получить оценку
    2019-05-02 15: 50: 10Z
  4. нет необходимости в sql, у нас есть linq! (Сарказм)
    2019-05-02 19: 23: 26Z

Я довел это до конца. Мне нужно было передать конкретные столбцы в группу, а не всю таблицу:

group new { rt.Score, pl.Created } by..

а не

group new { rt, pl } by...

Рабочий запрос:

from u in _context.Users
join pl in _context.PlanLogs on u.Id equals pl.UserId
join rt in _context.ResourceTypes on pl.ResourceTypeId equals rt.ID
join up in _context.UserProfile on pl.UserId equals up.UserId
group new { rt.Score, pl.Created } by new { u.DisplayName, up.ColorPreferences } into g
select new
{
DisplayName = g.Key.DisplayName,
ColorPrefs = g.Key.ColorPreferences,
Points = g.Sum(i => i.Score),
Plans = g.Count(),
MaxCreated = g.Max(i => i.Created).ToString("dd/MM/yyyy HH:mm")
}
    
0
2019-05-03 09: 58: 11Z
источник размещен Вот