程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C# 3.0入門系列(九)-之GroupBy操作

C# 3.0入門系列(九)-之GroupBy操作

編輯:關於C#

有朋友反饋說我提供的sample不能編譯。大概是版本的問題,可以到http://msdn2.microsoft.com/en-us/bb330936.aspx下載for beta1的版本。本節接著講groupby。

上一節,我們講了如何理解groupby返回的結果。本節會延這個思路闡述下去。先來看下面的例子

GroupBy操作中Select的匿名類

var q = from p in db.Products
group p by p.CategoryID into g
select new { CategoryID = g.Key, g };

本例中,select操作中使用了匿名類。本系列中第一次提到匿名類是在http://www.cnblogs.com/126/archive/2006/12/20/503519.html一文中。本文將再一次,闡述匿名類的理解。所謂匿名類,其實質,並不是匿名,而是編譯器幫你去創建了這麼一個類,在用戶看來,好像並沒有去創建,此所謂匿名類。也就是說,編譯器在編譯時,還是有這個類的,這個類是編譯器自己創建的,其名稱是編譯器界定的。 在上例的匿名類中,有2個property,一個叫CategoryID, 一個叫g。 大家要注意了,這個匿名類,其實質是對返回結果重新進行了包裝。而那個叫做g的property,就封裝了一個完整的分組。如圖,仔細比較和上篇圖的區別。

如果,使用下面的語句。

var q = from p in db.Products
group p by p.CategoryID into g
select new { CategoryID = g.Key,GroupSet = g };

只是把g重新命名為GroupSet.需要用下面的遍歷,獲取每個產品紀錄。

foreach (var gp in q)
{
 if (gp.CategoryID == 7)
 { 
  foreach (var p in gp.GroupSet)
  {

  }
 }
}

這裡groupby的操作相對難理解些,主要原因,它包含了整個分組的具體信息,而不是簡單的求和,取平均值等。如果在最終結果中,也就是在select語句中,不包含g的全部信息,而只是g的聚合函數。又會是怎麼樣的一番風景呢?

GroupBy中的Max, Min, Sum, Average,Count

如果,只想取每類產品中,單價為最大,用T-sql該怎麼辦呢?是不是要這麼來寫

SELECT MAX([t0].[UnitPrice]) AS [MaxPrice], [t0].[CategoryID]
FROM [dbo].[Products] AS [t0]
GROUP BY [t0].[CategoryID]

我們來看看,dlinq如何來做同樣的事情.如下,先按CategoryID歸類,然後,只取CategoryID值和同類產品中單價最大的。

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 MaxPrice = g.Max(p => p.UnitPrice)
};

在這裡,Max函數只對每個分組進行操作。我們來看看其結果

呀,這次,dlinq並沒有把組裡所有的紀錄都取出來的嗎。(請參考http://www.cnblogs.com/126/archive/2006/09/01/486388.html一文中的方法,配置sample.) dlinq只是簡單做了統計,並返回結果。

每類產品中,單價為最小的,

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 MinPrice = g.Min(p => p.UnitPrice)
};

每類產品的價格平均值

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 AveragePrice = g.Average(p => p.UnitPrice)
};

每類產品,價格之和

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 TotalPrice = g.Sum(p => p.UnitPrice)
};

各類產品,數量之和

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 NumProducts = g.Count()
};

如果用OrderDetails表做統計,會更好些,因為,不光可以統計同一種產品,還可以統計同一訂單。

接著統計,同各類產品中,斷貨的產品數量。使用下面的語句。

var q =
from p in db.Products
group p by p.CategoryID into g
select new {
 g.Key,
 NumProducts = g.Count(p => p.Discontinued)
};

在這裡,count函數裡,使用了Lambda表達式。在上篇中,我們已經闡述了g是一個組的概念。那在該Lambda表達式中的p,就代表這個組裡的一個元素或對象,即某一個產品。還可以使用where條件來限制最終篩選結果

var q =
from p in db.Products
group p by p.CategoryID into g
where g.Count() >= 10
select new {
 g.Key,
 ProductCount = g.Count()
};

這句在翻譯成sql語句時,欠套了一層,在最外層加了條件。

SELECT [t1].[CategoryID], [t1].[value2] AS [ProductCount]
FROM (
SELECT COUNT(*) AS [value], COUNT(*) AS [value2], [t0].[CategoryID]
FROM [dbo].[Products] AS [t0]
GROUP BY [t0].[CategoryID]
) AS [t1]
WHERE [t1].[value] >= @p0
-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [10]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 2.0.20612.0

GroupBy操作中GroupBy的匿名類

在第一次談到匿名類時,我們就提到不光Select操作可以使用匿名類,其他操作符也可以。但是,OrderBy不支持。請參考C#3.0入門系列(六)-之OrderBy操作

當用戶既想按產品的分類,又想按供應商來做分組,該怎麼辦呢。這時,我們就該使用匿名類。

var categories =
from p in db.Products
group p by new { p.CategoryID, p.SupplierID } into g
select new {g.Key, g};

在by後面,new出來一個匿名類。這裡,Key其實質是一個類的對象,Key包含兩個Property,一個是CategoryID,再一個是SupplierID ,要想取到具體CategoryID的值,需要g.Key.CategoryID,才能訪問到。我們來看dlinq翻譯的T-sql語句。

SELECT [t0].[SupplierID], [t0].[CategoryID]
FROM [dbo].[Products] AS [t0]
GROUP BY [t0].[CategoryID], [t0].[SupplierID]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 2.0.20612.0

先按CategoryID,再按SupplierID ,和匿名類中的循序一樣。

最後一個例子。

var categories =
from p in db.Products
group p by new { Criterion = p.UnitPrice > 10 } into g
select g;

按產品單價是否大於10分類。其結果為兩類,大於的是一類,小於及等於為另一類。好了,剩下的,大家自己多去領會。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved