Вопрос C # Linq: Как определить и посчитать предметы в наборе - PullRequest
3 голосов
/ 06 марта 2010

У меня есть друг, который использует c # Linq, чтобы сообщить о следующей таблице:

varchar(50) name
datetime    when

Клиент хочет выбрать, какие столбцы следует суммировать, например, Итого за этот год, Итого за прошлый год, Итого за две недели назад и т. Д. В каждом столбце будет время начала и окончания, которое они будут суммировать с помощью счетчика. Я сделал быстрое заявление для него:

select A.name as [Name],

    (select count(*) from mytable B where A.name = B.name and 
     datepart(yy, when) = datepart(yy,getdate())) as [This Year],

    (select count(*) from mytable B where A.name = B.name and
     datepart(yy, when) = (datepart(yy,getdate()) - 1)) as [Last Year]

from (select distinct name from mytable) A

Я также предложил ему сделать каждое поле вычисления делегатом, чтобы он мог содержать беспорядок вычислений вне запроса. Предполагая, что у каждого делегата будет дата начала и окончания, которая подсчитывает, сколько обращений происходит для каждого отдельного Имени, кто-нибудь захочет попробовать, как будет выглядеть код Linq c #?

Ответы [ 2 ]

5 голосов
/ 06 марта 2010

Довольно простой перевод:

DateTime Now = DateTime.Now;

DateTime thisYearStart = new DateTime(Now.Year, 1, 1);
DateTime thisYearEnd = thisYearStart.AddYears(1);
DateTime lastYearStart = thisYearStart.AddYears(-1);
DateTime lastYearEnd = thisYearStart

var query = dc.MyTable
  .GroupBy(a => a.Name)
  .Select(g => new
  {
    Name = g.Key,
    ThisYearCount = g
      .Count(b => thisYearStart <= b.When && b.When < thisYearEnd)
    LastYearCount = g
      .Count(b => lastYearStart <= b.When && b.When < lastYearEnd)
  });

Кстати, это рефакторированный sql, с которого я переводил:

SELECT A.Name as [Name],
  SUM(CASE WHEN @start1 <= A.When AND A.When < @end1 THEN 1 ELSE 0 END) as ThisYear,
  SUM(CASE WHEN @start2 <= A.When AND A.When < @end2 THEN 1 ELSE 0 END) as LastYear
FROM MyTable A
GROUP BY A.Name
2 голосов
/ 06 марта 2010

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

static IQueryable<IGrouping<TKey, TSource>> GroupWithinDates<TSource, TKey>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, TKey>> keySelector,
    Expression<Func<TSource, DateTime>> dateSelector,
    DateTime startDate,
    DateTime endDate
)
{
    return source
        .Where(item => dateSelector(item) >= startDate
                       && dateSelector(item) < endDate)
        .GroupBy(keySelector)
}

// Usage after setting startDate and endDate
var groups = mytable.GroupWithinDates(
               A => A.name, A => A.when, startDate, endDate)
// You can then transform to Name and Count
var groupCounts = groups.Select(g => new {Name = g.Key, Count = g.Count()};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...