博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#3.0入门系列(九)-之GroupBy操作
阅读量:6708 次
发布时间:2019-06-25

本文共 3770 字,大约阅读时间需要 12 分钟。

有朋友反馈说我提供的sample不能编译。大概是版本的问题,可以到下载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操作中使用了匿名类。本系列中第一次提到匿名类是在  一文中。本文将再一次,阐述匿名类的理解。所谓匿名类,其实质,并不是匿名,而是编译器帮你去创建了这么一个类,在用户看来,好像并没有去创建,此所谓匿名类。也就是说,编译器在编译时,还是有这个类的,这个类是编译器自己创建的,其名称是编译器界定的。 在上例的匿名类中,有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)
ExpandedBlockStart.gifContractedBlock.gif            
{
                
if (gp.CategoryID == 7)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{   
                    
foreach (var p in gp.GroupSet)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
                    
                    }
                }
            }
这里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并没有把组里所有的纪录都取出来的吗。(请参考一文中的方法,配置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不支持。请参考
当用户既想按产品的分类,又想按供应商来做分组,该怎么办呢。这时,我们就该使用匿名类。

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

 

TrackBack:http://www.cnblogs.com/126/archive/2007/07/10/812621.html

转载于:https://www.cnblogs.com/hdjjun/archive/2008/11/05/1327171.html

你可能感兴趣的文章
js进阶 12-14 jquery的事件触发函数是哪两个
查看>>
MySQL MERGE存储引擎 简介
查看>>
atitit。自己定义uml MOF EMF体系eclipse emf 教程o7t
查看>>
atitit.taskService 任务管理器的设计 v1
查看>>
编写jquery插件的分享
查看>>
机器学习 —— 概率图模型(学习:对数线性模型)
查看>>
2016百度编程题:蘑菇阵
查看>>
解决教学问题新感悟
查看>>
nyoj 37 回文字符串
查看>>
ASP.NET Core 1.0基础之依赖注入
查看>>
Excel里的单元格提行
查看>>
Matlab最短路径问题记录
查看>>
c语言单链表实现
查看>>
tcpdump非常实用的抓包实例
查看>>
ORACLE 日期函数 MONTHS_BETWEEN
查看>>
struts2.3+spring3.2+hibernate4.2例子
查看>>
进程调度
查看>>
北京地铁新机场线列车亮相调试 设计时速160公里/小时
查看>>
css布局基础总结
查看>>
Koa源码解析
查看>>