LINQ合并2个查询结果

时间:2015-10-23 02:23:23

标签: c# linq ado.net

数据表有5列

Name   Class   Course    Month    Score
Alex   C1      Math      12       90
Bob    C1      Chem      11       91
Alex   C2      Math      11       91
Alex   C1      Math      11       89
Bob    C1      Chem      12       97
Alex   C1      Math      10       94
Alex   C2      Chem      12       92
Bob    C2      Math      12       94

我想分组(姓名,班级)并在11月和12月获取最大数学分数和最大化学分数。继承我的查询代码

DataRow[] dr1 = dt.Select("Course = 'Math' AND Month > 10");
var result_one = dr1.AsEnumerable()
    .GroupBy(r => new { Name = r.Field<string>("Name"), Class = r.Field<string>("Class") })
    .Select(g => new
    {
        Name = g.Key.Name, 
        Class = g.Key.Class, 
        Max = g.Max(r => r.Field<int>("Score")),
        Max_Month = g.FirstOrDefault(gg => gg.Field<int>("Score") == g.Max(r => r.Field<int>("Score"))).Field<int>("Month"),
    }
    ).Distinct().ToList();


DataRow[] dr2 = dt.Select("Course = 'Chem'");
var result_two = dr2.AsEnumerable()
    .GroupBy(r => new { Name = r.Field<string>("Name"), Class = r.Field<string>("Class") })
    .Select(g => new
    {
        Name = g.Key.Name,
        Class = g.Key.Class,
        Max = g.Max(r => r.Field<int>("Score")),
        Max_Month = g.FirstOrDefault(gg => gg.Field<int>("Score") == g.Max(r => r.Field<int>("Score"))).Field<int>("Month"),
    }
    ).Distinct().ToList();

我可以输出这两个查询结果:

Name  Class    Math_Max_Month    Math_Max
Alex   C1      12                90
Alex   C2      11                91
Bob    C2      12                94
Name  Class    Chem_Max_Month    Chem_Max
Bob    C1      12                97
Alex   C2      12                92

但是如何将这两个结果合并为1个输出,例如:

Name  Class    Math_Max_Month    Math_Max  Chem_Max_Month   Chem_Max
Alex   C1      12                90        null             null
Alex   C2      11                91        12               92
Bob    C1      null              null      12               97
Bob    C2      12                94        null             null

我已尝试使用result_one.Concat(result_two)result_one.Union(result_two),但两者都不正确。

2 个答案:

答案 0 :(得分:1)

好吧,你的例子看起来有点复杂。所以我会在int[]而不是DataRow[]

给您答案
int[] first = new int[] { 3, 5, 6, 9, 12, 14, 18, 20, 25, 28 };
  int[] second = new int[] { 30, 32, 34, 36, 38, 40, 42, 44, 46, 48 };

  int[] result = first
    .Concat(second)
    .OrderBy(x => x)
    .ToArray();

输出

// 3, 5, 6, 9, 12, 14, 18, 20, 25, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48
  Console.Write(String.Join(", ", result));
从理论上讲,这应该适合你的情况,感觉我们只处理数组。

答案 1 :(得分:0)

这非常适合您的代码。

DataRow[] dr1 = dtt.Select("Course = 'Math' AND Month > 10");
        var result_one = dr1.AsEnumerable()
            .GroupBy(r => new { Name = r.Field<string>("Name"), Class = r.Field<string>("Class") })
            .Select(g => new
            {
                Name = g.Key.Name,
                Class = g.Key.Class,
                Max = g.Max(r => r.Field<int>("Score")),
                Max_Month = g.FirstOrDefault(gg => gg.Field<int>("Score") == g.Max(r => r.Field<int>("Score"))).Field<int>("Month"),
            }
            ).Distinct().ToList();


DataRow[] dr2 = dtt.Select("Course = 'Chem'");
        var result_two = dr2.AsEnumerable()
            .GroupBy(r => new { Name = r.Field<string>("Name"), Class = r.Field<string>("Class") })
            .Select(g => new
            {
                Name = g.Key.Name,
                Class = g.Key.Class,                    
                Chem_Max = g.Max(r => r.Field<int>("Score")),
                Chem_Max_Month = g.FirstOrDefault(gg => gg.Field<int>("Score") == g.Max(r => r.Field<int>("Score"))).Field<int>("Month"),
            }
            ).Distinct().ToList();

左加入......

var lstLeftJoin = (from a in result_one
                           join b in result_two
                           on new { a.Name, a.Class } equals new { b.Name, b.Class }
                           into gj
                           from subpet in gj.DefaultIfEmpty()
                           select new { a.Name, a.Class, Math_Max_Month = a.Max_Month, Math_Max = a.Max, Chem_Max_Month = (subpet == null ? 0 : subpet.Chem_Max_Month), Chem_Max = (subpet == null ? 0 : subpet.Chem_Max) }).ToList();

正确加入......

  var lstRightJoin = (from a in result_two
                            join b in result_one
                            on new { a.Name, a.Class } equals new { b.Name, b.Class }
                            into gj
                            from subpet in gj.DefaultIfEmpty()
                            select new { a.Name, a.Class, Math_Max_Month = (subpet == null ? 0 : subpet.Max_Month), Math_Max = (subpet == null ? 0 : subpet.Max), a.Chem_Max_Month, a.Chem_Max }).ToList();

Finaly the Union ...

var lstUnion = lstLeftJoin.Select(s => new { Name = s.Name, Class = s.Class, Math_Max_Month = s.Math_Max_Month, Math_Max = s.Math_Max, Chem_Max_Month = s.Chem_Max_Month, Chem_Max = s.Chem_Max }).Union(lstRightJoin.Select(s => new { Name = s.Name, Class = s.Class, Math_Max_Month = s.Math_Max_Month, Math_Max = s.Math_Max, Chem_Max_Month = s.Chem_Max_Month, Chem_Max = s.Chem_Max })).OrderBy(o => o.Name).ThenBy(c => c.Class).ToList();

<强> RESULT

Name  Class    Math_Max_Month    Math_Max  Chem_Max_Month   Chem_Max
Alex   C1      12                90        null             null
Alex   C2      11                91        12               92
Bob    C1      null              null      12               97
Bob    C2      12                94        null             null