我正在构建一个步骤跟踪Web应用程序。我正在使用最新的EF Core。我正在与三个表进行交互:
我想要的是获得所有WellnessGroups以及该组的总步数。如果还没有附加到该组的步骤,我希望NULL值为0.我有这个SQL语句,它给了我所需的数据:
SELECT wg.Name, SUM(ISNULL(wsl.StepCount, 0)) AS steps
FROM dbo.WellnessGroup AS wg
LEFT JOIN dbo.WellnessGroupUser AS wgu
ON wgu.WellnessGroupId = wg.Id
LEFT JOIN dbo.WellnessStepsLog AS wsl
ON wsl.EmployeeId = wgu.AzureAdUserId
GROUP BY wg.Name
ORDER BY steps DESC;
我已经设法在我的控制器上放了两个LINQ表达式,它只给我一些与它们相关联的步骤的WellnessGroups,并且如果没有步骤则不给我WellnessGroup数据:
var query = _dbContext.WellnessGroupUser
.Include(x => x.WellnessGroup)
.Join(_dbContext.WellnessStepsLog, group =>
group.AzureAdUserId, steps => steps.EmployeeId,
(group, steps) => new
{
Steps = steps.StepCount,
Date = steps.TrackedDate,
Group = group.WellnessGroup.Name
}).Where(x => x.Date >= yearToDate).Where(x => x.Date <= endDate);
var stepsByGroup = query
.GroupBy(x => x.Group)
.Select(s => new
{
Group = s.Key,
Date = s.Max(x => x.Date),
Steps = s.Sum(x => x.Steps)
});
答案 0 :(得分:0)
一种方法是查询所有WellnessGroups并将内部构建为第二个子查询。像这样:
var query =
db.WellnessGroup.Select(wg => new {
wg.WellnessGroupId,
sum = (int?) wg.WellnessGroupUser
.Sum(wgu => wgu.Employee.WellnessStepsLog.Sum(wsl => wsl.StepCount))
});
注意,转换为(int?)很重要。否则,sum假定为int,如果没有行的总和,则会导致InvalidOperationException。
另一种方法是首先构建所有总和。然后使用WellnessGroups进行外部联接:
// sum up all stepcounts
var q1 =
from wgu in db.WellnessGroupUser
from wsl in db.WellnessStepsLog
where wgu.EmployeeId == wsl.EmployeeId
group wsl.StepCount by wgu.WellnessGroupId
into g
select new {WellnessGroupId = g.Key, Sum = g.Sum()};
// join with all WellnessGroups
var q2 =
from wg in db.WellnessGroup
join s in q1 on wg.WellnessGroupId equals s.WellnessGroupId into sj
from sum in sj.DefaultIfEmpty()
select new {wg, sum = (int?) sum.Sum};
编辑:
由于OP后来在评论中询问如何按多个字段进行分组。以下是按WellnessGroup.WellnessGroupId
和WellnessStepsLog.TrackedDate
月份分组的示例。 GroupBy
中的字段可以放在new { ... }
中,可以有多个字段。因此,第一个查询为每个可能的WellnessGroup / Month组合创建一个行。第二个查询与之前一样执行WellnessGroup的外连接:
var q1 =
from wgu in db.WellnessGroupUser
from wsl in db.WellnessStepsLog
where wgu.EmployeeId == wsl.EmployeeId
group wsl.StepCount by new { wgu.WellnessGroupId, wsl.TrackedDate.Month }
into g
select new {g.Key.WellnessGroupId, g.Key.Month, Sum = g.Sum()};
// join with all WellnessGroups
var q2 =
from wg in db.WellnessGroup
join s in q1 on wg.WellnessGroupId equals s.WellnessGroupId into sj
from sum in sj.DefaultIfEmpty()
select new {wg.WellnessGroupId, Month = (int?) sum.Month, Sum = (int?) sum.Sum};