专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »DotNet » groupby:C#3.0入门系列( 9)-的GroupBy操作 »正文

groupby:C#3.0入门系列( 9)-的GroupBy操作

来源: 发布时间:星期二, 2009年2月17日 浏览:6次 评论:0
  有朋友反馈说我提供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 o g
          select { CategoryID = g.Key, g };


  本例中select操作中使用了匿名类本系列中第次提到匿名类是在http://www.cnblogs.com/126/archive/2006/12/20/503519.html文中本文将再阐述匿名类理解所谓匿名类其实质并不是匿名而是编译器帮你去创建了这么个类在用户看来好像并没有去创建此所谓匿名类也就是说编译器在编译时还是有这个类这个类是编译器自己创建其名称是编译器界定 在上例匿名类中有2个property个叫CategoryID, 个叫g 大家要注意了这个匿名类其实质是对返回结果重新进行了包装而那个叫做gproperty就封装了个完整分组如图仔细比较和上篇图区别



  如果使用下面语句

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


  只是把g重新命名为GroupSet.需要用下面遍历获取每个产品纪录

      foreach (var gp in q)
      {
         (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 o g
    select {
      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 o g
    select {
      g.Key,
      MinPrice = g.Min(p => p.UnitPrice)
    };


  每类产品价格平均值

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


  每类产品价格的和

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


  各类产品数量的和

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


  如果用OrderDetails表做统计会更好些不光可以统计同种产品还可以统计同订单

  接着统计同各类产品中断货产品数量使用下面语句

  var q =
    from p in db.Products
    group p by p.CategoryID o g
    select {
      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 o g
    where g.Count >= 10
    select {
      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入门系列( 6)-的OrderBy操作

  当用户既想按产品分类又想按供应商来做分组该如何办呢这时我们就该使用匿名类

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


  在by后面出来个匿名类这里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 { Criterion = p.UnitPrice > 10 } o g
    select g;


  按产品单价是否大于10分类其结果为两类大于小于及等于为另好了剩下大家自己多去领会



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: