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

转载 2007年09月28日 17:30:00

有朋友反馈说我提供的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分类。其结果为两类,大于的是一类,小于及等于为另一类。好了,剩下的,大家自己多去领会。


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

C#3.0入门系列(九)-之GroupBy操作 有朋友反馈说我提供的sample不能编译。大概是版本的问题,可以到http://msdn2.microsoft.com/en-us/bb330936.a...
  • starlessnt
  • starlessnt
  • 2008年03月19日 15:46
  • 352

C#3.0入门系列(八)-之GroupBy操作

换一种写作风格。本节讲groupby操作。在所有的Linq To Sql操作中,GroupBy是最难理解的一个。因为,这里和Sql的出入较大。而Group真的就能返回n多组。打开vs,新建一工程,加入...
  • Night_Elf
  • Night_Elf
  • 2007年09月28日 17:28
  • 620

USB入门系列总结

USB是什么呢?一说USB是You SB的意思,即“你傻B”的意思。另一种说法是USB其实是美国的弟弟,因为美国叫USA,USB当然是他的弟弟了。     那么USB到底是什么呢?其实USB是通...
  • u013916997
  • u013916997
  • 2014年05月27日 17:09
  • 836

USB入门系列之一:USB概述

USB是什么呢?一说USB是You SB的意思,即“你傻B”的意思。另一种说法是USB其实是美国的弟弟,因为美国叫USA,USB当然是他的弟弟了。...
  • kevinhg
  • kevinhg
  • 2010年09月30日 23:44
  • 2112

C#3.0介绍(八)-之GroupBy操作

换一种写作风格。本节讲groupby操作。 在所有的Linq To Sql操作中,GroupBy是最难理解的一个。因为,这里和Sql的出入较大。而Group真的就能返回n多组。 打开vs,新建...
  • iamdll
  • iamdll
  • 2014年03月21日 15:31
  • 312

C#3.0入门系列(十一)-之In, Like操作

有这么一个例子,寻找一个表中的某个字段介于某个给定的集合该怎么办?Sql写起来很简单,比如:Select * from table where id in (2,3, 4, 5)。 就是寻找id字段为...
  • Night_Elf
  • Night_Elf
  • 2007年09月28日 17:34
  • 622

C#3.0入门系列(六)-之OrderBy操作

本节讲orderby操作.我突然在想这么一个问题,读者会T-SQL吗?要是不知道,那我写的是不是太简单了呢?做个调查哦,不知道的举手.OrderBy操作简单的,按雇用日期排序,默认为升序       ...
  • Night_Elf
  • Night_Elf
  • 2007年09月28日 16:54
  • 675

C#3.0入门系列(五)-之Where操作

从本节开始,本文正式更名为C#3.0入门系列。先发布一则消息,VS2007 Beta版本已经发布咯,下载地址:http://www.microsoft.com/downloads/details.as...
  • Night_Elf
  • Night_Elf
  • 2007年09月28日 16:53
  • 641

C#3.0入门系列(十)-之Join操作

 本节讲join操作。我们知道,T-sql中,有三种最基本的join,inner join, left join, 和right join。 而dlinq并不支持right join。道理很简单,ri...
  • Night_Elf
  • Night_Elf
  • 2007年09月28日 17:33
  • 635

C#3.0入门系列(十一)-之In, Like操作

C#3.0入门系列(十一)-之In, Like操作 有这么一个例子,寻找一个表中的某个字段介于某个给定的集合该怎么办?Sql写起来很简单,比如:Select * from table where id...
  • starlessnt
  • starlessnt
  • 2008年03月19日 16:34
  • 465
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#3.0入门系列(九)-之GroupBy操作
举报原因:
原因补充:

(最多只允许输入30个字)