Abdulnazark Ответов: 3

Как получить функцию Sql datediff() в linq


Как получить функцию Sql datediff() в linq, мне нужно получить средние дни между двумя днями

мой SQL-запрос

select  year(recDate) as year1,DateName(month,(recDate)) as mnth,
relDept, count(*) as tot,
avg(datediff(day,RecDate,isnull(intl_ack,getdate())+1)) as avg1,

avg(datediff(day,RecDate,isnull(Resol_Date,getdate())+1)) as res1,
sum(case when status='Open' then 1 else 0 end) as open1

 from  Cust_Complaints  group by year(recDate),relDept,DateName(month,(recDate))


нужно преобразовать запрос в LINQ

Maciej Los

Примеры данных были бы полезны.

Abdulnazark

TrID RecDate ModeOfComp RelDept Intl_Ack Resol_Date ClosureDate Status
27 19/01/14 Служба Писем 00:00.0 19/02/14 19/02/14 Закрыто
28 05/02/14 Факс 00:00.0 20/02/14 20/02/14 Закрыт
29 25/03/14 Служба Электронной Почты 00:00.0 30/03/14 30/03/14 Закрыто
30 06/04/14 Получение И Отправление Факсов 00:00.0 18/05/14 20/05/14 Закрыт
31 08/04/14 Прямое Обслуживание 00:00.0 12/04/14 15/04/14 Закрыто
32 09/04/14 Телефонная Служба 00:00.0 10/04/14 12/04/14 Закрыта
33 28/04/14 телефонная служба 00:00.0 02/06/14 ноль закрыт
34 12/05/14 факс строительство 00:00.0 15/05/14 ноль закрыт
35 12/05/14 служба писем 00:00.0 20/05/14 NULL закрыто
36 12/05/14 Служба электронной почты 00:00.0 20/05/14 NULL Open
37 30/04/14 телефонная служба 00:00.0 03/05/14 NULL Open
38 24/06/14 телефонная служба 00:00.0 02.07.14 NULL закрыта
40 25/06/14 факс NESales 00:00.0 NULL NULL Open
41 30/06/14 факс NESales 00:00.0 NULL NULL Open
42 27.07.14 Служба электронной почты 00:00.0 03.08.14 NULL закрыта
43 25/09/14 факс 00:00.0 NULL NULL Open
44 30/09/14 Служба электронной почты 00:00.0 NULL NULL Open
45 30/09/14 телефонная конструкция 00:00.0 31/10/14 NULL Open

Abdulnazark

прилагаемые примеры данных будут оценены, если вы сможете опубликовать полный запрос LINQ

Maciej Los

Используйте виджет ответа, если вы хотите уведомить меня о комментарии.

3 Ответов

Рейтинг:
19

Maciej Los

Пожалуйста, прочтите мой комментарий к этому вопросу. Мы не можем "преобразовать" ваш sql-запрос в Linq-запрос, не видя данных.

Вы можете посмотреть здесь:
SqlMethods.Метод DateDiffDay[^]
LINQ to SQL советы и рекомендации[^]

[Править 2]

var qry = from a in md
        group a by new{Year = a.RecDate.Year, Month = a.RecDate.ToString("MMM"), Dept = a.RelDept} into grp
        select new
        {
            Year = grp.Key.Year,
            Month = grp.Key.Month,
            Dept = grp.Key.Dept,
            AvgIA = grp.Average(g=>(g.RecDate - (g.Intl_Ack !=null ? g.Intl_Ack : DateTime.Today)).Days),
            AvgRD = grp.Average(g=>(g.RecDate - (g.Resol_Date !=null ? g.Resol_Date : DateTime.Today)).Days),
            SumOp = grp.Sum(g=>g.Status=="Open" ? 1 : 0)
        };


Abdulnazark

Как проверить нуль

Maciej Los

Смотрите обновленный ответ ;)

Abdulnazark

это прекрасно, за исключением a.RecDate.ToString("МММ")

спасибо,

ошибка заключается в следующем

Исключение типа 'System.Исключение notsupportedexception' произошел в и EntityFramework.От SQLServer.dll, но не был обработан в пользовательском коде

Дополнительная информация: LINQ to Entities не распознает систему метода.String ToString(System.String)' метод, и этот метод не может быть переведен в выражение хранилища.

Maciej Los

Учтите, что я не вижу вашей модели сущности. Вы должны изменить его в соответствии с вашими потребностями.
Вы можете использовать: a.RecDate.Month

Abdulnazark

работал ниже
var qry = (от a В cm.Cust_Complaints.Список()
группа а по новому году { Year = a.RecDate.Ценность.Год, месяц = a.RecDate.Ценность.ToString("MMMM"), Dept = a.RelDept } в grp
выберите новый
{
Год = grp.Key.Year,
Месяц = grp.Key.Month,
Отдел = ВРП.Ключ.Отдел,
AvgIA = grp.Средняя(г =&ГТ; ((г.Intl_Ack != значение null ? г. Intl_Ack.Значение : Значение Типа Datetime.Сегодня.Дата) - г.RecDate.Ценность).Дней) + 1,
AvgRD = grp.Среднее значение(g => ((g.Resol_Date != null ? g.Resol_Date.Значение : Дата-Время.Сегодня.Дата) - г.RecDate.Ценность).Дней) + 1),


SumOp = ВРП.Сумма(г =&ГТ; г. Статус == "Открыть" ? 1 : 0)
});
Управления gridview1.Источник данных = qry по;
Управления gridview1.Привязку();
спасибо,

Maciej Los

Всегда пожалуйста ;)
Я рад, что могу вам помочь ;)

Рейтинг:
1

Thomas Daniels

Эквивалент C# будет выглядеть следующим образом:

DateTime endDate = ...;
DateTime startDate = ...;
int dayDiff = (endDate - startDate).Days;

Вышеизложенное возвращает разницу между двумя датами. Если у вас есть строковое представление даты, используйте значение datetime.Разбор[^] чтобы разобрать его.

Вы можете поместить приведенный выше код в метод, который можно вызвать из вашего запроса LINQ.


Maciej Los

Хороший совет!

Рейтинг:
1

aodennison

Решение № 2 не совсем LinqToSql
Он работает только из-за ToList(). ToList() , как и AsEnumerable (), заставляет остальную часть выражения вычисляться на стороне клиента; это Linq, но не LinqToSql и может быть неприемлемо для больших результирующих наборов.

Метод executequery
Один трюк, если у вас уже есть SQL, состоит в том, чтобы использовать что-то вроде:
свойство DataContext.ExecuteQuery<tresult>(запрос, optionalParameterValues);

Вам придется решить, что использовать для TResult.

LinqToSql выполняет SQL на сервере
LinqToSql принимает некоторые C# expressions & functions и сопоставляет их с SQL, чтобы выражение вычислялось на сервере. Не все выражения могут быть переведены, что приводит к ошибкам во время выполнения. Решение состоит в том, чтобы найти то, что C# может быть переведено в SQL-код, и лучшее место для его выполнения-сервер/клиент.

В случае OP, поскольку выполняется "группировка по", На самом деле может быть более эффективным принудительно выполнить запрос на стороне клиента. LinqToSql иногда обрабатывает "group by" как n запросов, где n-количество групп.

Некоторые методы не могут быть сопоставлены с SQL. Другие выражения могут казаться сопоставленными с SQL и выполняться на хосте, но это не так; например, значения, которые могут быть определены до запроса на клиенте. Таким образом, вы можете использовать DateTime.Добавьте, когда операнды доступны перед запросом, но не для значения столбца.

Часто небольшое экспериментирование может найти C#, который будет работать. В этом случае все оказывается проще, чем ожидалось, потому что пока свидание.Add не может быть сопоставлен, другие выражения с датами могут быть сопоставлены. Вот несколько примеров:

DateTime SqlDateMin = новый DateTime(1999, 1, 1);
DateTime SqlDateMax = new DateTime(9999, 12, 31);

var query3 =
от ue в Company_Diff
пусть startDate = ue.SysRowStartDate == null ? SqlDateMin : ue.SysRowStartDate
пусть endDate = ue.SysRowEndDate == null ? SqlDateMax : ue.SysRowEndDate
пусть следующий = начальная дата + период.От дней(1)
пусть год = дата окончания.Ценность.Год
пусть diff = ue.SysRowEndDate - startDate

выберите новый { уе.SysRowEndDate, УП.SysRowStartDate, сравнения, следующий, год };


Вам нужно обрабатывать нулевые даты, иначе вы получите исключения, когда будете запрашивать данные с нулевыми значениями и пытаться добавить их.
Опять же, чтобы увидеть результирующий SQL, используйте LinqPad и просмотрите его в таблице SQL.