2010-03-12 92 views
48

讓我們說,我有一個表稱爲 項目(ID INT,完成INT,總INT)獲取兩列的總和一個LINQ查詢

我可以用兩個查詢做到這一點:

int total = m.Items.Sum(p=>p.Total) 
int done = m.Items.Sum(p=>p.Done) 

但我想這樣做在一個查詢中,這樣的事情:

var x = from p in m.Items select new { Sum(p.Total), Sum(p.Done)}; 

當然還有一種方法叫聚合函數從LINQ語法...?

回答

68

這將這樣的伎倆:

from p in m.Items 
group p by 1 into g 
select new 
{ 
    SumTotal = g.Sum(x => x.Total), 
    SumDone = g.Sum(x => x.Done) 
}; 
+7

或者當產品沒有唯一的標識符,你可以用p寫'羣p成g'。 – Steven 2010-03-12 11:30:48

+1

雖然做了修改: from p.m.Items p組通過p.Id轉換爲g select new {SumTotal = g.Sum(r => r.Total),SumDone = g.Sum (r => r.Done)} – Axarydax 2010-03-12 11:33:48

+1

你說得對,在查詢中已經使用了'p'。修復。 – Steven 2010-03-12 11:49:02

1

在一名助手的元組類,無論是你自己或—在.NET 4級—通用的標準,你可以這樣做:

var init = Tuple.Create(0, 0); 

var res = m.Items.Aggregate(init, (t,v) => Tuple.Create(t.Item1 + v.Total, t.Item2 + v.Done)); 

而且res.Item1是總的Total柱和res.Item2Done列。

8

如何

m.Items.Select(item => new { Total = item.Total, Done = item.Done }) 
      .Aggregate((t1, t2) => new { Total = t1.Total + t2.Total, Done = t1.Done + t2.Done }); 
9

總結表,組由一個常數:

from p in m.Items 
group p by 1 into g 
select new { 
    SumTotal = g.Sum(x => x.Total), 
    SumDone = g.Sum(x => x.Done) 
} 
+0

請有人發佈vb.net版本? – Zeus 2016-02-02 01:10:51

+0

@Zeus這裏是VB.Net代碼,從g In From p In m.ItemsGroup p By 1New With {_ \t Key .SumTotal = g.Sum(Function(x)x.Total),_ \t Key。 SumDone = g.Sum(Function(x)x.Done)_ }您可以在這裏轉換代碼[鏈接](http://converter.telerik.com/) – 2016-03-15 06:46:36

+0

@Sibeesh,感謝您的幫助 – Zeus 2016-03-15 07:08:13

5

搞清楚提取的款項或者在我的其他代碼中的其他集合混淆了我,直到我記得我構建的變量是一個Iqueryable。假設我們有我們的訂單組成的數據庫中的表,我們要生產的ABC公司的一個總結:

var myResult = from g in dbcontext.Ordertable 
       group p by (p.CUSTNAME == "ABC") into q // i.e., all of ABC company at once 
       select new 
{ 
    tempPrice = q.Sum(x => (x.PRICE ?? 0m)), // (?? makes sure we don't get back a nullable) 
    tempQty = q.Sum(x => (x.QTY ?? 0m)) 
}; 

現在最有趣的部分 - tempPrice和tempQty沒有在任何聲明,但他們必須是一部分myResult的,不是?如下訪問它們:

Console.Writeline(string.Format("You ordered {0} for a total price of {1:C}", 
           myResult.Single().tempQty, 
           myResult.Single().tempPrice)); 

也可以使用許多其他的Queryable方法。

1
//Calculate the total in list field values 
//Use the header file: 

Using System.Linq; 
int i = Total.Sum(G => G.First); 

//By using LINQ to calculate the total in a list field, 

var T = (from t in Total group t by Total into g select g.Sum(t => t.First)).ToList(); 

//Here Total is a List and First is the one of the integer field in list(Total) 
-2

當您使用組由,所以你有一個項目的兩個集合的LINQ創建項目的新的集合。

下面就以這兩個問題的解決方案:在一個迭代和

  • 避免重複你的項目的集合

    1. 總結成員的任何量

    代碼:

    public static class LinqExtensions 
    { 
        /// <summary> 
        /// Computes the sum of the sequence of System.Double values that are obtained 
        /// by invoking one or more transform functions on each element of the input sequence. 
        /// </summary> 
        /// <param name="source">A sequence of values that are used to calculate a sum.</param> 
        /// <param name="selectors">The transform functions to apply to each element.</param>  
        public static double[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double>[] selectors) 
        { 
        if (selectors.Length == 0) 
        { 
         return null; 
        } 
        else 
        { 
         double[] result = new double[selectors.Length]; 
    
         foreach (var item in source) 
         { 
         for (int i = 0; i < selectors.Length; i++) 
         { 
          result[i] += selectors[i](item); 
         } 
         } 
    
         return result; 
        } 
        } 
    
        /// <summary> 
        /// Computes the sum of the sequence of System.Decimal values that are obtained 
        /// by invoking one or more transform functions on each element of the input sequence. 
        /// </summary> 
        /// <param name="source">A sequence of values that are used to calculate a sum.</param> 
        /// <param name="selectors">The transform functions to apply to each element.</param> 
        public static double?[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double?>[] selectors) 
        { 
        if (selectors.Length == 0) 
        { 
         return null; 
        } 
        else 
        { 
         double?[] result = new double?[selectors.Length]; 
    
         for (int i = 0; i < selectors.Length; i++) 
         { 
         result[i] = 0; 
         } 
    
         foreach (var item in source) 
         { 
         for (int i = 0; i < selectors.Length; i++) 
         { 
          double? value = selectors[i](item); 
    
          if (value != null) 
          { 
          result[i] += value; 
          } 
         } 
         } 
    
         return result; 
        } 
        } 
    } 
    

    這裏的你必須做的總結方式:

    double[] result = m.Items.SumMany(p => p.Total, q => q.Done); 
    

    下面是一個普通的例子:

    struct MyStruct 
    { 
        public double x; 
        public double y; 
    } 
    
    MyStruct[] ms = new MyStruct[2]; 
    
    ms[0] = new MyStruct() { x = 3, y = 5 }; 
    ms[1] = new MyStruct() { x = 4, y = 6 }; 
    
    // sum both x and y members in one iteration without duplicating the array "ms" by GROUPing it 
    double[] result = ms.SumMany(a => a.x, b => b.y); 
    

    ,你可以看到

    result[0] = 7 
    result[1] = 11 
    
  • 1

    這已經被回答了,但其他的答案仍然會做在收集多次迭代(多個呼叫或者創建大量可能很好的中間對象/元組,但是如果不是這樣,那麼您可以創建一個擴展方法(或多個),它以傳統方式進行,但很適合LINQ表達式。

    這樣的擴展方法是這樣的:

    public static Tuple<int, int> Sum<T>(this IEnumerable<T> collection, Func<T, int> selector1, Func<T, int> selector2) 
    { 
        int a = 0; 
        int b = 0; 
    
        foreach(var i in collection) 
        { 
         a += selector1(i); 
         b += selector2(i); 
        } 
    
        return Tuple.Create(a, b); 
    } 
    

    而且你可以使用它像這樣:

    public class Stuff 
    { 
        public int X; 
        public int Y; 
    } 
    
    //... 
    
    var stuffs = new List<Stuff>() 
    { 
        new Stuff { X = 1, Y = 10 }, 
        new Stuff { X = 1, Y = 10 } 
    }; 
    
    var sums = stuffs.Sum(s => s.X, s => s.Y);