EFCore 2.2 GroupBy Sum 和 DateDiff
EFCore 2.2 GroupBy Sum and DateDiff
我正在尝试将以下 SQL 转换为 EF Core 查询,但我收到警告,将在本地计算 GroupBy 和 Sum。反正目前有没有写这个它会完全翻译成 SQL?
SELECT UserId, ST.StatusId, SUM(DATEDIFF(MINUTE, StartDate, ISNULL(EndDate,GETDATE()))) AS Time
FROM StatusTransaction ST
WHERE
TeamManagerId = 1
AND StartDate >= N'01-01-2019'
AND ISNULL(EndDate,GETDATE()) <= N'01-02-2019'
GROUP BY UserId, ST.StatusId
ORDER BY UserId
这些是我使用过的 EF 查询:
var efFunction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => Microsoft.EntityFrameworkCore.EF.Functions.DateDiffMinute(st.StartDate, st.EndDate)) // null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var simpleDateSubtraction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.EndDate.Value.Subtract(st.StartDate).Minutes)// null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var groupBySimpleSum = await context
.Where(st => st.TeamManagerId == tmId)
.GroupBy(st => new { st.TeamManagerId, st.OperationsManagerId })
.Select(g => new
{
g.Key.OperationsManagerId,
g.Key.TeamManagerId,
Foo = g.Sum(st => st.UserId) // nonsense but a simple column to sum, this translates fully to SQL
}).ToListAsync(cancellationToken).ConfigureAwait(false);
首先,EF Core 仍然不支持转换 TimeSpan
操作,并且 DateTime
差异产生 TimeSpan
,因此 EF.Functions.DateDiff
方法是正确的方法。
其次,它仍然可以翻译 GroupBy
仅在简单成员访问器表达式上的聚合。所以你必须在 Select
之前 GroupBy
表达式:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.Select(st => new
{
st.UserId,
st.StatusId,
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});
或使用 GroupBy
重载,它允许预先选择聚合源:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.GroupBy(st => new { st.UserId, st.StatusId }, st => new
{
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});
我正在尝试将以下 SQL 转换为 EF Core 查询,但我收到警告,将在本地计算 GroupBy 和 Sum。反正目前有没有写这个它会完全翻译成 SQL?
SELECT UserId, ST.StatusId, SUM(DATEDIFF(MINUTE, StartDate, ISNULL(EndDate,GETDATE()))) AS Time
FROM StatusTransaction ST
WHERE
TeamManagerId = 1
AND StartDate >= N'01-01-2019'
AND ISNULL(EndDate,GETDATE()) <= N'01-02-2019'
GROUP BY UserId, ST.StatusId
ORDER BY UserId
这些是我使用过的 EF 查询:
var efFunction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => Microsoft.EntityFrameworkCore.EF.Functions.DateDiffMinute(st.StartDate, st.EndDate)) // null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var simpleDateSubtraction = await context
.Where(st => st.TeamManagerId == tmId && st.StartDate >= dateFrom && (st.EndDate ?? DateTime.Now) <= dateTo)
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.EndDate.Value.Subtract(st.StartDate).Minutes)// null check not done on end date - (st.EndDate ?? DateTime.Now) causes an error here
}).ToListAsync(cancellationToken).ConfigureAwait(false);
var groupBySimpleSum = await context
.Where(st => st.TeamManagerId == tmId)
.GroupBy(st => new { st.TeamManagerId, st.OperationsManagerId })
.Select(g => new
{
g.Key.OperationsManagerId,
g.Key.TeamManagerId,
Foo = g.Sum(st => st.UserId) // nonsense but a simple column to sum, this translates fully to SQL
}).ToListAsync(cancellationToken).ConfigureAwait(false);
首先,EF Core 仍然不支持转换 TimeSpan
操作,并且 DateTime
差异产生 TimeSpan
,因此 EF.Functions.DateDiff
方法是正确的方法。
其次,它仍然可以翻译 GroupBy
仅在简单成员访问器表达式上的聚合。所以你必须在 Select
之前 GroupBy
表达式:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.Select(st => new
{
st.UserId,
st.StatusId,
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.GroupBy(st => new { st.UserId, st.StatusId })
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});
或使用 GroupBy
重载,它允许预先选择聚合源:
var query = context
.Where(st => st.TeamManagerId == tmId
&& st.StartDate >= dateFrom
&& (st.EndDate ?? DateTime.Now) <= dateTo
)
.GroupBy(st => new { st.UserId, st.StatusId }, st => new
{
Time = EF.Functions.DateDiffMinute(st.StartDate, st.EndDate ?? DateTime.Now)
})
.Select(g => new
{
g.Key.UserId,
g.Key.StatusId,
Time = g.Sum(st => st.Time)
});