带有表连接、case 语句、计数、group by 子句的 Linq 查询

Posted

技术标签:

【中文标题】带有表连接、case 语句、计数、group by 子句的 Linq 查询【英文标题】:Linq query with table joins,case statements, count, group by clauses 【发布时间】:2012-02-19 19:20:29 【问题描述】:

我想运行一个 linq 查询,它将值返回到我的自定义 DTO。这个特定的 linq 查询需要考虑来自多个表的连接,使用 switch case 语句、count (*) 和 group by

这是查询的 SQL 版本示例,我需要一个 LinQ 等价物...

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 类型列表的查询

感谢您的宝贵时间...

【问题讨论】:

您能否将表前缀(c.cpd.slm.)添加到您的查询中,以便我们知道哪个列属于哪个表? 【参考方案1】:

当您尝试将该 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)
;

然而,这个查询过于复杂,并且完全忽略了 Entity Framework 对模型了解更多并生成所有外键作为实体属性的事实。除此之外,使用 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)        
;

这要简单得多,并且(如果我没记错的话)具有相同的结果。

【讨论】:

我需要一个左连接到 db.TabSLM 中的 slm。您将如何修改此查询? 将我标记为答案,并在此处发布一个新问题。

以上是关于带有表连接、case 语句、计数、group by 子句的 Linq 查询的主要内容,如果未能解决你的问题,请参考以下文章

GROUP BY + CASE 语句

SQL group by with Case 语句

Group by 语句不适用于 Select Case

如何使用 CASE 语句而不必将其放入 GROUP BY

带有 GROUP BY 的这个 MySQL 视图的 MS 版本?

跨表使用group by,case when的问题