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

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

转载于:https://www.cnblogs.com/jiangj/archive/2010/08/24/1806998.html

【转】C#3.0入门系列(九)-之GroupBy操作相关推荐

  1. C# 3.0入门系列

    目录导航 1 C# 3.0 入门系列(一) 从linq开始引C# 3.0. 2 C# 3.0入门系列(二) 数据库的准备,引入Linq To Sql的准备. 3 C# 3.0入门系列(三) 第一个Li ...

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

    从本节开始,本文正式更名为C#3.0入门系列.先发布一则消息,VS2007 Beta版本已经发布咯,下载地址: http://www.microsoft.com/downloads/details.a ...

  3. WF4.0入门系列1——创建一个简单的工作流

    WF4.0入门系列1--创建一个简单的工作流 打开VS2010,选择文件-新建-项目,选择Workflow项 工作流台应用程序,在名称处输入chapter01,选择合适的位置,这里默认,单击确定. V ...

  4. C# 3.0入门系列(三)

    从本节开始,笔者将会和大家一起开始体验dlinq了.前面我们准备了数据库,也对数据库之间的关系做了初步的了解.有了数据库之后,数据和对象是一个什么样的关系呢?从dlinq的设计来看,它主要是为了解决d ...

  5. C# 3.0 入门系列(一)

    谈到dlinq,就不得不先说linq.让我们先看看什么是linq.linq是 Language Integrated Query的缩写.那么事实上dlinq就是 Database Language I ...

  6. C# 3.0入门系列(二)

    在第一篇中,我已经和大家简单介绍了linq.也和大家提起linq是C# 3.0里的一个特性.不过,你去装linq priview时,你会发现,它提供了许多vb的linq代码.从现在的情况看,linq会 ...

  7. Vue 2.0 入门系列(15)学习 Vue.js 需要掌握的 es6 (2)

    类与模块 类 es6 之前,通常使用构造函数来创建对象 // 构造函数 User function User(username, email) { this.username = username; ...

  8. Vue2.0入门系列——父子组件间通信

    1.子组件更新,父组件不变 点击"按钮"按钮,子组件数据被修改,父组件数据不变  =========>>>>>>  项目源代码, <hea ...

  9. Microsoft Web Farm Framework (WFF) 2.0 入门系列之一:WFF 介绍

    Microsoft Web Farm Framework (WFF) 2.0 是微软开发的.基于IIS 7.x的小插件,能够帮助我们轻松实现Web网站的高性能.高可用性.如果想做基于IIS的反向代理, ...

最新文章

  1. python request.get()_使用Python request.get解析无法一次加载的html代码
  2. chrome插件开发记录(1)——解决问题“清单文件缺失或不可读”
  3. PHP不能精确表达小数 PHP除法结果不准确 php 为什么数字除法不准确 PHP浮点数运算不准确的问题...
  4. 好的高等教育 赫胥黎
  5. mysql-5.7.10-winx64 MySQL服务无法启动,服务没有报告任何错误的解决办法
  6. linux indent命令: 调整C原始代码文件的格式
  7. 升级版授权系统+盗版追踪+域名IP双授权+在线加密系统
  8. golang和C的输出格式化对齐
  9. null索引表键值_MySQL 的B+树索引
  10. SQLi LABS Less-26 联合注入+报错注入+布尔盲注+时间盲注
  11. 腾讯往事:微信其实就是第四代 QQ 邮箱
  12. CSS定义通用透明效果
  13. html怎么用excel打开乱码,excel打开是乱码,详细教您excel打开是乱码怎么解决
  14. 【Python游戏】Python基于pygame和random模块开发的一个拼图小游戏 | 附带源码
  15. Linux 第一次学习笔记
  16. 如何防止别人偷窥我给宝贝儿娜娜的信
  17. 机器学习——回归中的相关度与R平方值及其应用
  18. 做自己喜欢的事情,是假的,改变世界也是假的
  19. 在北京坐公交和大人流量地铁站换乘
  20. 微信内点击链接或扫描二维码直接打开手机默认浏览器打开指定网页

热门文章

  1. 【差分隐私的Advanced composition到底是什么?】差分隐私系统学习记录(四)
  2. Java网络爬虫该如何学习
  3. 如何将一个目录下的所有文件,合并成一个文件
  4. Markdown--绘制流程图(flowchart)
  5. 使你的C/C++代码支持Unicode
  6. SpringMVC 视图解析器及拦截器
  7. JAVA SAX解析XML文档
  8. IntelliJ IDEA常用快捷键——基于Eclipse
  9. freeswitch 发update sip消息_VOS修改SIP注册端口
  10. linq to sql 行转列_SQL进阶:SQL高级编程语法实例