0

假设我有一个“数据库”定义为:

// Baked goods vendors
   var vendor = new[] {
    new { ID = 1, Baker = "Pies R Us", StMnemon = "NY", Items = 8, Rating = 9 },
    new { ID = 2, Baker = "Mikes Muffins", StMnemon = "CA", Items = 5, Rating = 9 },
    new { ID = 3, Baker = "Best Bakers", StMnemon = "FL", Items = 2, Rating = 5 },
    new { ID = 4, Baker = "Marys Baked Treats", StMnemon = "NY", Items = 8, Rating = 7 },
    new { ID = 5, Baker = "Cool Cakes", StMnemon = "NY", Items = 4, Rating = 9 },
    new { ID = 6, Baker = "Pie Heaven", StMnemon = "CA", Items = 12, Rating = 9 },
    new { ID = 7, Baker = "Cakes N More", StMnemon = "GA", Items = 6, Rating = 8 },
    new { ID = 8, Baker = "Dream Desserts", StMnemon = "FL", Items = 2, Rating = 7 }
};

// Locations
var location = new[] {
    new {ID= 1, State = "New York", Mnemonic = "NY"},
    new {ID= 2, State = "Massachusetts", Mnemonic = "MA"},
    new {ID= 3, State = "Ohio", Mnemonic = "OH"},
    new {ID= 4, State = "California", Mnemonic = "CA"},
    new {ID= 5, State = "Florida", Mnemonic = "FL"},
    new {ID= 6, State = "Texas", Mnemonic = "TX"},
    new {ID= 7, State = "Georgia", Mnemonic = "GA" }
};

我想构建一个相当于 SQL 查询的查询:

SELECT   State, Rating, SUM(Items) AS 'Kinds'
FROM     vendor, location
WHERE    vendor.StMnemon = location.Mnemonic
GROUP BY State, Rating

此查询中有两件事是:

  1. GROUP BY 涉及多个表,并且
  2. 结果包含未出现在分组条件中的列的总和。

我已经在有关按多个表分组对不在 group-by 中的列求和的帖子中看到了解决方案。问题在于,将两者结合起来并不会真正复制关系查询。

我尝试使用以下代码在 LINQ 中复制它:

var query = from v in vendor
           join l in location
           on v.StMnemon equals l.Mnemonic
           orderby v.Rating ascending, l.State
           select new { v, l };

var result = from q in query
           group q by new { 
               s = q.l.State, 
               r = q.v.Rating
/* ==> */    , i = q.v.Items
           } into grp
        select new 
        {
            State = grp.Key.s,
            Rating = grp.Key.r
/* ==> */ , Kinds = grp.Sum(k => grp.Key.i)
        };

这导致:

=================================
State           Rating  Kinds
Florida         5       2
Florida         7       2
New York        7       8
Georgia         8       6
California      9       5
California      9       12
New York        9       8
New York        9       4
=================================

然而,上面给出的 SQL 查询给出了这个结果:

=========================
State       Rating  Kinds
Florida     5       2
Florida     7       2
New York    7       8
Georgia     8       6
California  9       17
New York    9       12
=========================

The discrepancy is because there seems to be no place to put additional columns, other than in the grouping criteria, which of course changes the grouped result. Commenting out the two lines indicated by the /* ==> */ comment in the code above will give the same grouping as the SQL result, but of course that removes the summation field that I want to include.

How do we group multiple tables in LINQ and include additional criteria without changing the grouped result?

4

2 回答 2

2

something like this seems to return the same as the SQL query:

var result = from v in vendor
             from l in location
             where l.Mnemonic == v.StMnemon
             group v by new { l.State, v.Rating } into grp
             orderby grp.Key.Rating ascending, grp.Key.State
             select new {State = grp.Key.State, Rating = grp.Key.Rating, Kinds = grp.Sum(p=>p.Items)};

foreach (var item in result)
        Console.WriteLine("{0}\t{1}\t{2}", item.State, item.Rating, item.Kinds);
于 2012-11-20T21:53:43.833 回答
2

You can do an aggregation outside of the group:

var query = from v in vendor
           join l in location
           on v.StMnemon equals l.Mnemonic
           orderby v.Rating ascending, l.State
           select new { v, l };

var result = from q in query
           group q by new { 
               s = q.l.State, 
               r = q.v.Rating
           } into grp
        select new 
        {
            State = grp.Key.s,
            Rating = grp.Key.r,
            Kinds = grp.Sum(g => g.Items)
        };

Grouping is a little tricky to grasp - it returns an IGrouping that has one property - Key. The actual items in that grouping are returned by the GetEnumerator() function that lets you treat the group as a collection of those items, meaning you can do aggregation on the items within that group.

于 2012-11-20T21:54:01.377 回答