Как выбрать совокупность из нескольких столбцов (без группировки по)? - PullRequest
1 голос
/ 13 февраля 2012

Скажем, у меня есть сводная таблица, подобная этой:

AcitivityCache
(
   pkId (bigint, PK),
   Date (DateTime),
   OfficeId (int, FK)
   TransactionCount (int),
   RejectCount (int),
   InvitationCount (int),
   RequestCount (int)
   ...
   --more counts here--
   ...
)

Теперь мне нужно получить общую сумму за период времени (без группировки по офисам, только суммы), которую я могу сделать с SQLвот так:

 SELECT SUM(TransactionCount) as TotalTxCount, SUM(RejectCount) as TotalRejectCount, ...
 FROM ActivityCache 
 WHERE [Date] between '2011-02-01' and '2012-02-01'

Как мне этого добиться с помощью linq?Большинство решений, которые я видел до сих пор, имеют некоторую группировку.Но для этого случая мне не нужна группировка, только итоги.Я могу сделать так:

DateTime dateFrom, toDate; // initialized later
...
var q = dbContext.ActivityCaches
                 .Where(a=> a.Date > fromDate && a.Date <= toDate)
                 .GroupBy(a=> 1)
                 .Select(g=> new 
                             {
                                TotalTransactionCount = g.Sum(a => a.TransactionCount),
                                TotalRejectCount = g.Sum(a => a.RejectCount),
                                ...
                                ...
                             });

Или я могу сначала получить столбцы, а затем программно взять сумму.Или я могу использовать SP (не нравится в этом случае).Есть идеи получше (без группы)?

PS: я не смогу изменить схему БД

Ответы [ 4 ]

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

Я не думаю, что LINQ to Entities имеет хороший запрос для этой ситуации.
Другое решение использует Entity SQL (ESQL)

var fromDate = new DateTime(2011, 02, 01);
var toDate = new DateTime(2012, 02, 01);
var esql = @"select 
          sum(it.TransactionCount) as SumOfTransactionCount,
          sum(it.RejectCount) as SumOfRejectCount
               from ActivityCaches as it
               where it.Date > @fromDate and it.Date <= @toDate";
var query = CreateQuery<DbDataRecord>(esql,
        new ObjectParameter("fromDate", fromDate) ,
        new ObjectParameter("toDate", toDate));
1 голос
/ 13 февраля 2012

Другие способы:

  1. Использовать Entity SQL
  2. Применить 3 отдельных SUM с
0 голосов
/ 13 февраля 2012

Из вашего вопроса не ясно, где вы хотите сохранить результат. Если вы планируете хранить его в двух переменных, вы можете получить данные, использовать метод расширения .Where () для фильтрации по диапазону дат, а затем использовать метод расширения .Sum () для вычисления значения суммы. Что-то вроде этого:

var result = your_query.Where(m => m.Date >= startingDate && m.Date <= endingDate);
var totalTxCount = result.Sum(m => m.TransactionCount);
var totalRejectCount = result.Sum(m => m.RejectCount);
0 голосов
/ 13 февраля 2012

Метод Linq Aggregate () позволяет суммировать без группировки, как показано ниже. Я боюсь, что я не настроил его для БД, поэтому я не гарантирую, что ошибка Linq to Sql не появится. Если это произойдет, вы можете попробовать объяснить ToList () на ActivityCaches () перед выполнением Aggregate (), но после where ().

Обновление

Я обновил код для работы и модель EF. Создал небольшую модель EF для замены SomeEntry и обновил данные, чтобы убедиться, что я читаю из БД.

EF Model for ActivityLog

private static ActivityLog Aggregate(ActivityLog agg, ActivityLog entry) {
    agg.TranCount += entry.TranCount;
    agg.ReqCount += entry.ReqCount;
    return agg;
}

[TestMethod]
public void AggregateFirstThree() {

    var context = new TestDBEntities();

    var startDate = new DateTime(2012, 1, 1);
    var endDate = new DateTime(2012, 1, 3);

    var aggregate = new ActivityLog();

    context.ActivityLogs.Where(entry => entry.Timestamp >= startDate && entry.Timestamp <= endDate).Aggregate(aggregate, Aggregate);

    Assert.AreEqual(66, aggregate.TranCount);
    Assert.AreEqual(36, aggregate.ReqCount);

}

[TestMethod]
public void AggregateLastThree() {

    var context = new TestDBEntities();

    var startDate = new DateTime(2012, 1, 4);
    var endDate = new DateTime(2012, 1, 6);

    var aggregate = new ActivityLog();

    context.ActivityLogs.Where(entry => entry.Timestamp >= startDate && entry.Timestamp <= endDate).Aggregate(aggregate, Aggregate);

    Assert.AreEqual(75, aggregate.TranCount);
    Assert.AreEqual(45, aggregate.ReqCount);

}

чч,
Алан.

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