2012-02-13 55 views
1

說我有這樣的彙總表:如何選擇多列的聚合(無分組)?

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:我不會成爲能夠改變DB模式

+1

那麼,T-SQL是*隱含*做分組操作,它只是所有的記錄都在同一組,這是一樣的,你用你的'的GroupBy(做什麼a => 1)'。你有什麼特別的理由不喜歡這個嗎? – AakashM 2012-02-13 09:23:17

+0

沒有理由不喜歡:)。我只是想知道是否有更多的方法。 – mshsayem 2012-02-14 03:14:04

回答

2

我不認爲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)); 
+2

雖然我不喜歡字符串查詢。但是,似乎你說得對:「我不認爲LINQ to Entities對這種情況有一些好的質疑」。我會堅持「.GroupBy(G => 1)」 – mshsayem 2012-02-14 03:45:18

1

另一種方式:

  1. 使用實體SQL
  2. 應用3個獨立的SUM小號
+0

你能展示一些例子/鏈接嗎? – mshsayem 2012-02-13 04:37:08

+1

@mshsayem,http://msdn.microsoft.com/en-us/library/bb387145。aspx – 2012-02-13 09:25:52

0

LINQ的聚合(使用)方法允許在沒有如下分組求和。恐怕我沒有將它設置爲對數據庫,所以我不能保證Linq to Sql錯誤不會彈出。如果發生這種情況,可以在執行Aggregate()之前但在where()之後,在ActivityCaches()上嘗試一個顯式ToList()。

更新

我更新的代碼和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); 

} 

心連心,
艾倫。

+0

這不會與EF – 2012-02-13 12:21:41

+0

工作@Adrian Iftode剛剛試了一下,EF模型,工作得很好。甚至不需要添加ToList()。將更新代碼以反映更改。 – AlanT 2012-02-13 13:45:39

+0

不錯,我很確定:P – 2012-02-13 13:52:00

0

從您的問題中您不清楚要存儲結果的位置。如果您打算將其存儲在兩個變量中,則可以獲取數據,使用.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

是的,但在這種情況下,會有多個查詢... – mshsayem 2012-02-14 03:10:48