2017-03-29 102 views
3

我有一个具有一对多关系的数据库表[Table1]。
这个相关的表[Table2]有一个类型字段,它是一个字符串。linq-to-sql按连接表中的字符串列表组

 
Table 1   Table 2 
Field | Type  Field | Type 
------|-----  ---------|----- 
Id | int  Id  | int 
       Table1Id | int 
       Type  | string 

我想创建的类型的每个组合出现的频率, 的总结和我试图做的DB尽可能多的工作,因为它是把一切都写进内存太慢。

代码我有工作,但似乎重复我。

 items 
     .Where(x => x.Table2s.Count > 1) 
     .Select(x => new 
     { 
      Type = x.Table2s.Select(y => y.Type) 
     }) 
     .ToList() // into memory as string.join has no translation into sql 
     .Select(x => new 
     { 
      Type = string.Join(",", x.Type) // no sql translation 
     }) 
     .GroupBy(x => x.Type) // can't work on IEnumerable[string] 
     .Select(x => new Result() 
     { 
      Type = x.Key, 
      Count = x.Count() 
     }) 
     .OrderByDescending(x => x.Count) 
     .ToList(); 

有没有一种办法按该字符串列表,这样我可以做的DB分组,并减少在我的代码

+1

为什么你'的string.join()'所有类型和组在那?你是否试图检测具有相同字段定义的类型的重复项? –

+0

@JeroenvanLangen对不起,我试图显示table1中的记录已链接到表2类型的每种组合的次数: 类型a,b,c = 5 |类型a,c = 10 |类型d,f = 1 –

+0

您可以将一个int字段添加到“表1”中,通过该字段可以制作标记枚举的类型元素。然后你可以按他们的总数分组。 –

回答

0

LINQ到SQL不支持select语句的数量AggregateString.Join或相应的SQL技巧,所以除非你想使用存储过程,否则一些工作必须发生在客户端。

另一种方法是首先创建分组,然后将它们发送回服务器以计算匹配,但这看起来不像是一种收益。

我认为你能做的最好的是一样的东西

var sqlans = items.Where(x => x.Table2s.Count > 0).AsEnumerable(); 
var ans = sqlans.Select(x => String.Join(",", x.Table2s.Select(t2 => t2.Type).OrderBy(ty => ty).ToArray())).GroupBy(ty => ty, ty => ty, (key, g) => new { key, Count = g.Count() }); 

我下令Type小号属于一个item所以分组时,他们会匹配。 sqlans部分将由服务器执行,但其余部分必须在客户端上执行以处理String.Join

而不是使用EF我会被诱惑到工作表2的(做左半加入,如果你可能有孤儿表2项)直接

var sqlans = Table2.GroupBy(t2 => t2.Table1Id, t2 => t2.Type, (key, g) => g).AsEnumerable(); 
var ans = sqlans.Select(x => String.Join(",", x.OrderBy(ty => ty).ToArray())).GroupBy(ty => ty, ty => ty, (key, g) => new { key, Count = g.Count() });