带有表联接、case语句、count和groupby子句的Linq查询

本文关键字:groupby 子句 查询 Linq count 语句 case | 更新日期: 2023-09-27 18:25:03

我想运行一个linq查询,该查询将向我的自定义DTO返回值。这个特殊的linq查询需要考虑来自多个表的联接,使用switchcase语句、count(*)和groupby

这是查询的SQL版本示例,我需要一个相当于。。。

select 
slm.SLType, 
count(c.EStatID) as EStat, 
COUNT(cpd.TrId) as Training,
COUNT(
CASE WHEN cpd.TrStat=  44 THEN  1 
     WHEN cpd.TrStat!=  44 THEN NULL 
     WHEN cpd.TrStat IS NULL  THEN  NULL 
END) as TrainingComplete,
COUNT(
CASE WHEN cpd.CndAssess =  44 THEN  1 
     WHEN cpd.CndAssess !=  44 THEN NULL 
     WHEN cpd.CndAssess IS NULL  THEN  NULL 
END) as AssessmentComplete
from TabC c , TabCPD cpd, TabSLM slm 
where cpd.SLid = slm.SLid
and c.Id= cpd.CID
and c.O_Id = 1
group by slm.SLType 

它以以下格式返回记录。我将每条记录作为一个新行,字段之间用逗号分隔。下面的数字只是的一个例子

TypeA, 0 , 1 , 1, 0 
TypeB, 1 , 0 , 1, 0

我正试图以下面的格式创建一个linq查询,但没有太多运气

var query = 
    from c in TabC, ...... 
    select new MyCustomTableC_DTO
    {
      DTOproperty = c.MatchingTable property,....
    }

MyCustomTableC_DTO将为查询中的每个字段都有一个属性。知道如何做到这一点吗?我将使用该查询来构建MyCustomTableC_DTO 类型的列表

谢谢你抽出时间。。。

带有表联接、case语句、count和groupby子句的Linq查询

当您尝试逐行将SQL语句转换为LINQ时,您会得到如下结果:

from row in (
    from c in db.TabC
    from cpd in db.TabPD
    from slm in db.TabSLM
    where cpd.SLid == slm.SLid
    where c.Id == cpd.CID
    where c.O_Id == 1
    select new { c, cpd, slm })
group row in row.slm.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.c.EstatID != null),
    Training = g.Count(r => r.cpd.TrId != null),
    TrainingComplete =
        g.Count(r => r.cpd.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.cpd.CndAssess == 44)
};

然而,这个查询使事情过于复杂,并完全忽略了这样一个事实,即实体框架对模型了解得更多,并将所有外键生成为实体上的属性。除此之外,使用LINQ,您必须经常以另一种方式处理事情。例如,在您的情况下,不要从TabCTabSLM实体开始,而是从TabPD开始,因为该表是交叉表。有了这些知识,我们可以这样编写LINQ查询:

from cpd in db.TabCPDs
where cpd.TabC.O_Id == 1
group cpd by cpd.TabSLM.SLType into g
select new
{
    SLType = g.Key,
    EStat = g.Count(r => r.TabC.EstatID != null),
    Training = g.Count(r => r.TrId != null),
    TrainingComplete =
        g.Count(r => r.TrStat == 44),
    AssessmentComplete =
        g.Count(r => r.CndAssess == 44)        
};

这要简单得多,(如果我没有弄错的话)也有同样的结果。