关于linq:按多列和计数分组

Group by Multiple Columns and Count

我有以IEnumerable形式出现的表1和表2。这两个表都有EDOCX1列(1)和EDOCX1列(2)。

我想在Column1上进行一个左外部联接,并希望获得Table2中存在的行的计数,并将记录加载到数据表中。

我试过下面的问题

1
2
3
4
5
6
7
8
9
10
var query = from p in Table1
            join q in Table2 on p.Field<string>("Column1") equals q.Field<string>("Column1") into pq
            from xyz in pq.DefaultIfEmpty()
            group xyz by new { Col1 = p.Field<string>("Column1"), Col2 = p.Field<string>("Column2") } into g
            select dtFinalData.LoadDataRow(new object[]
            {
                g.Key.Col1,
                g.Key.Col2,                              
                g.Count
            }, false);

由于"g"代表分组数据,g.count对于表2中没有条目的行返回1。我想为这些行返回"0"。

输入:

表1

1
2
3
Col1Val1       Col2Val1

Col1Val2       Col2Val2

表2

1
2
3
Col1Val1       Col2Val1

Col1Val1       Col2Val1

电流输出:

1
2
3
Col1Val1        Col2Val1    2

Col2Val2        Col2Val2    1

预期结果:

1
2
3
Col1Val1        Col2Val1    2

Col2Val2        Col2Val2    0

我已经查看了linq-left-join、group-by和count,但是我不能将它们应用到我的查询中…

你能帮我解决这个问题吗?


let是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from p in Table1
let p1 = p.Field<string>("Column1")
let p2 = p.Field<string>("Column2")
let qs =
  from q in Table2
  where p1 == q.Field<string>("Column1")
  select q
let qCount = qs.Count()
select dtFinalData.LoadDataRow(new object[]
{
  p1,
  p2,
  qCount
}, false);

因为我没有加入,所以我不必分组。每个结果行对应于表1中的一行。

以下是GroupJoin解决方案:

1
2
3
4
5
6
7
8
9
10
11
from p in Table1
let pkey = new { c1 = p.Field<string>("Column1"), c2 = p.Field<string>("Column2") }
join q in Table2 on pkey equals
  new { c1 = q.Field<string>("Column1"), c2 = q.Field<string>("Column2") }
  into qs
select dtFinalData.LoadDataRow(new object[]
{
  pkey.c1,
  pkey.c2,
  qs.Count()
}, false);

这里有一个连接和组解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
from p in Table1
let pkey = new { c1 = p.Field<string>("Column1"), c2 = p.Field<string>("Column2") }
join q in Table2 on pkey equals
  new { c1 = q.Field<string>("Column1"), c2 = q.Field<string>("Column2") }
  into right
from q in right.DefaultIfEmpty()
group q by pkey into g
select dtFinalData.LoadDataRow(new object[]
{
  g.Key.c1,
  g.Key.c2,
  g.Count(q => q != null)
}, false);