如何创建Linq2Sql查询,该查询将从链接表中对记录进行分组并计算2个计数字段

时间:2012-04-18 05:15:05

标签: c# mysql linq-to-sql bltoolkit

在这里,我找到了如何使用Linq2Sql连接表并计算链接记录的数量LINQ - Left Join, Group By, and Count

我已经实现了它,它对我来说没问题:以下表达式

var v = from c in db.GetTable<Country>()
        join t0 in db.GetTable<Team>() on c.Id equals t0.CountryId into t1
        from team in t1.DefaultIfEmpty()
        group team by c.Id into teamsGrouped
        select new CountryTeamsInfo
            {
                CountryId = teamsGrouped.Key,
                TeamsTotal = teamsGrouped.Count(),
                // TeamsWithoutOwnerFree = teamsGrouped.Count(t => t.OwnerId==0)
            }
            ;
         List<CountryTeamsInfo> res = v.ToList();

生成以下查询:

SELECT c.Id, Count(*) as c1
FROM countries c
LEFT JOIN teams t1 ON c.Id = t1.Country
GROUP BY c.Id 

实际上,我还需要计算那些OwnerId字段不等于0的链接器记录。

看起来我应该在linq表达式中取消注释该行(TeamsWithoutOwnerFree = teamsGrouped.Count(t =&gt; t.OwnerId == 0)),但这不起作用,尝试执行会导致错误:

  

字典中没有给定的密钥

查询没有来到SQL日志文件,我无法在调试器中检查它。

从“球队”表中计算满足其他条件的那些线的正确方法应该是什么。

P.S。如果重要,我使用C#4.0,MySql 5.1和BLToolkit 4.1

3 个答案:

答案 0 :(得分:1)

也许尝试使用GroupJoin()进行查询:

var result = db.GetTable<Country>()
               .GroupJoin(db.GetTable<Team>(),
                   c => c.Id,
                   t => t.CountryId,
                   (country, teams) => new
                   {
                       CountryId = country.Id,
                       TeamsTotal = teams.Count(),
                       TeamsWithoutOwnerFree = teams.Count(t => t.OwnerId == 0)
                   })
               .ToList();

答案 1 :(得分:0)

由于RePierre帮助,我能够找到正确的查询:

var v = db.GetTable<Country>().Where(country => country.Allowed)
                    .GroupJoin(
                        db.GetTable<Team>(),
                        country => country.Id,
                        team => team.CountryId,
                        (country, teams) => new CountryTeamsInfo
                                                {
                                                    CountryId = country.Id,
                                                    TeamsTotal = teams.Count(),
                                                    TeamsWithoutOwnerFree = teams.Count(t => t.OwnerId != 0),
                                                }
                    ).GroupJoin(
                        db.GetTable<Team>().Where(te=>te.OwnerId==0),
                        cti => cti.CountryId,
                        team => team.CountryId,
                        (cti, teams) => new CountryTeamsInfo
                        {
                            CountryId = cti.CountryId,
                            TeamsTotal = cti.TeamsTotal,
                            TeamsWithoutOwnerFree = teams.Count(t => t.OwnerId != 0),
                        }
                    )
                    ;

我关心的是它使用2个子查询...将尝试优化它。任何想法都会很棒

P.S。实际上,生成的SQL查询看起来也很丑陋:

SELECT
cti.Id as Id1,
cti.c1 as c11,
(
    SELECT
        Count(*)
    FROM
        teams te
    WHERE
        cti.Id = te.Country AND te.User = 0
) as c2
FROM
(
    SELECT
        country.Id,
        (
            SELECT
                Count(*)
            FROM
                teams t1
            WHERE
                country.Id = t1.Country
        ) as c1
    FROM
        countries country
    WHERE
        country.allow

答案 2 :(得分:0)

这是在我的环境中有效的查询:

from c in db.GetTable<Country>()
where c.Allowed
select new CountryTeamsInfo
{
    CountryId = c.Id,
    TeamsTotal = db.GetTable<Team>().Count(t => t.CountryId == c.Id && t.Allowed),
    TeamsHasOwner = db.GetTable<Team>().Count(t => t.CountryId == c.Id && t.Allowed && t.OwnerId != 0),
}

不是最好的解决方案(我需要重复团队选择标准t。允许在每个子查询中),但仍能正常运行并且生成的SQL很好。