Вычислить среднее значение в базе данных SQL

#c# #sql-server #entity-framework-core

#c# #sql-сервер #сущность-фреймворк-ядро

Вопрос:

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

Используя Entity Framework Core, я использовал следующее:

 var average = await games
  .Where(x => x.Finish.HasValue)
  .AverageAsync(x => Math.Round((x.Finish.Value - x.Start).TotalDays, 2));
  

Похоже, это выполняется в памяти.

Как я могу вычислить среднее значение по базе данных (SQL)?

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

1. Каков целевой тип базы данных (поскольку в настоящее время не существует универсального способа выполнения вычислений временных интервалов на стороне сервера)?

2. Я использую SQL Server

3. AverageAsync сам должен быть рассчитан в базе данных. Ваше выражение вычисляется в памяти, вероятно, из-за TimeSpan операций, подобных TotalDays .

Ответ №1:

Проблема заключается не в Average , а в вычислении временного интервала — в настоящее время EF Core (2.x) не поддерживает общую SQL-трансляцию вычислений временного интервала.

Для SQLServer, хотя вы могли бы использовать некоторые из методов DateDiff, представленных в EF Core 2.1. Все они возвращают int значения, поэтому вы не можете использовать напрямую DateDiffDay для получения эквивалента TimeSpan.TotalDays , но вы могли бы использовать DateDiffHour / 24d или DateDiffMinute / (24d * 60) и т.д. для имитации этого.

Например,

 var average = await games
    .Where(x => x.Finish.HasValue)
    .AverageAsync(x => Math.Round(EF.Functions.DateDiffHour(x.Start, x.Finish.Value) / 24d, 2));
  

переводится в

   SELECT AVG(ROUND(DATEDIFF(HOUR, [x].[Start], [x].[Finish]) / 24.0E0, 2))
  FROM [Game] AS [x]
  WHERE [x].[Finish] IS NOT NULL