Linq-to-SQL группировать по датам-периодам в зависимости от параметра (ежедневно, ежемесячно ....) - PullRequest
1 голос
/ 20 февраля 2012

Я пытаюсь сделать запрос Linq to SQL, который возвращает результаты группировки дат. Задача состоит в группировке ежедневных / еженедельных / ежемесячных / квартальных зависимостей от перечисляемого параметра (периодичности). Ниже мой текущий запрос Linq to SQL:

var TotalGroupedInvoices = from c in entidades.InvoicesView
                     group c by (periodo == periodicity.Daily) ? c.InvoiceDate.Date :
                                      period == periodicity.Weekly?     c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek) :
                                      period == periodicity.Monthly? new DateTime(c.InvoiceDate.Year,c.InvoiceDate.Month ,1) :
                                      period == periodicity.Quarterly? new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1) :
                                      period == periodicity.Anual ? new DateTime(c.InvoiceDate.Year, 1, 1) : inicio into Periods
                     select new
                     {

                         period = Periods.Key,
                         Total = Periodos.Sum(c => c.Total)
                     };

Для уточнения взгляните на фрагмент кода квартального периода:

period == periodicity.Quarterly? new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1)

Таким образом, для дат в первом квартале, таких как: январь / 12/2012, январь / 15/2012 или март / 20/2012, я сгруппировал их все в начале квартала: январь / 1/2012, так что это работает как и ожидалось.

Сначала меня интересует эффективность запросов. Что Вы думаете об этом? Возможно, было бы лучше перевести периоды в целые числа для эффективности SQL Server и повторно перевести на периоды даты на клиенте, но я не уверен в этом.

С другой стороны, еженедельная групповая работа группирует даты еженедельно в первое воскресенье каждой недели:

period == periodicity.Weekly? c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek)

... но это неправильно для меня, потому что я из Испании, а недели начинаются в понедельник. Как я могу исправить группы недели, чтобы принять это во внимание?

Итак, подведем итог:

  • Как насчет эффективности запросов Linq to SQL?
  • Как я могу группировать это еженедельно, но учитывая недели с понедельника по воскресенье?

Большое спасибо! PD: извините за мой уровень английского.

Ответы [ 2 ]

2 голосов
/ 20 февраля 2012

Чтобы ответить на первую часть, вы на самом деле не хотите передавать значение enum в базы данных и позволять ему решать, какую ветвь кода использовать.У вас есть вся информация для локального принятия решения.

Expression<Func<InvoicesView, DateTime>> groupingExpr = c => c.InvoiceDate.Date;

if (period == periodicity.Weekly)
{
  groupingExpr = c => c.InvoiceDate.Date.AddDays(-(double)c.InvoiceDate.DayOfWeek);
}
else if (period == periodicity.Monthly)
{
  groupingExpr = c => new DateTime(c.InvoiceDate.Year,c.InvoiceDate.Month ,1);
}
else if (period == periodicity.Quarterly)
{
  groupingExpr = c => new DateTime(c.InvoiceDate.Year, c.InvoiceDate.Month - (c.InvoiceDate.Month % 3) +1, 1);
}
else if (period == periodicity.Anual
{
  groupingExpr = c => new DateTime(c.InvoiceDate.Year, 1, 1);
}


var TotalGroupedInvoices = entidades.InvoicesView 
  .GroupBy(groupingExpr)
  .Select(grouped => new {
    period = grouped.Key,
    Total = grouped.Sum(c => c.Total)   
  });

Вот лучшее, что я могу сделать, чтобы смешать groupingExpr с синтаксисом понимания запросов:

var TotalGroupedInvoices = from grouped in entidades.InvoicesView.GroupBy(groupingExpr)
  select new {
    period = grouped.Key,
    Total = grouped.Sum(c => c.Total)   
  };
0 голосов
/ 20 февраля 2012

Чтобы ответить на вторую часть, вам просто нужно сделать некоторую «дневную» арифметику.Вы можете сделать это встроенно или как отдельную функцию (например, метод расширения):

public static DateTime FirstDayOfWeek (this DateTime date)  
{  
  double offset = (date.DayOfWeek == DayOfWeek.Sunday) ? -6 : (DayOfWeek.Monday - date.DayOfWeek);  
  return date.AddDays(offset);  
}

Тогда в вашем LINQ:

period == periodicity.Weekly ? c.InvoiceDate.FirstDayOfWeek

Однако, учитывая, что вы извлекаете это из SQL, выможет просто захотеть посмотреть функции даты там, например, DATEPART и вернуть их в ваших запросах

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...