简体   繁体   English

linq-to-sql group by连接表中的字符串列表

[英]linq-to-sql group by list of strings from a joined table

I have a DB table [Table1] with a one to many relationship. 我有一个DB表[Table1]具有一对多的关系。
This related table [Table2] has a type field which is a string. 该相关表[Table2]具有类型字段,该字段是字符串。

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

I am trying to create a summary of how often each combination of types occurs, and am attempting to do as much work on the DB as possible as it is too slow to bring it all into memory. 我正在尝试创建每种类型组合出现频率的摘要,并尝试尽可能多地在DB上进行操作,因为它太慢而无法将其全部存入内存。

The code I have works but seems repetitive to me. 我的代码有效,但对我来说似乎重复。

        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();

Is there a way to group by this list of strings so that I can do the grouping on the DB and also reduce the number of select statements in my code 有没有办法按此字符串列表进行分组,以便我可以对数据库进行分组,还可以减少代码中的select语句数量

Linq to SQL doesn't support Aggregate or String.Join or corresponding SQL tricks, so unless you want to use a stored procedure, some of the work has to happen on the client side. Linq to SQL不支持AggregateString.Join或相应的SQL技巧,因此除非您想使用存储过程,否则一些工作必须在客户端进行。

One alternative would be to create the groupings first and then send them back to the server to count the matches, but that doesn't seem like a gain. 另一种方法是首先创建分组,然后将它们发送回服务器以计算匹配,但这似乎不是一个好处。

I think the best you can do is something like 我认为你能做的最好就是这样

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() });

I ordered the Type s belonging to an item so they would match up when grouped. 我订购了属于某个itemType ,以便在分组时匹配。 The sqlans portion would be executed by the server, but the rest has to execute on the client to process the String.Join . sqlans部分将由服务器执行,但其余部分必须在客户端上执行以处理String.Join

Instead of using EF I would be tempted to work on Table2 (doing left semi join if you might have orphan Table2 entries) directly 而不是使用EF我会试图在Table2上工作(如果您可能有孤立的Table2条目,则执行左半连接)

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() });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM