SQL到LINQ有多个join,count和left join

时间:2018-03-12 22:06:38

标签: sql linq join left-join sql-to-linq-conversion

我用多个JOIN(包括LEFT JOIN)编写了此SQL请求 它给了我预期的结果

SELECT DISTINCT c.Id, 
       c.Title, 
       COUNT(v.Id) AS 'Nb_V2',
       COUNT(DISTINCT v.IdUser) AS 'Nb_V1',
       r.cnt AS 'Nb_R'
FROM TABLE_C c
JOIN TABLE_V v on c.Id = v.Id
LEFT JOIN ( 
    SELECT Id, COUNT(*)  AS cnt 
    FROM TABLE_R 
    GROUP BY Id
) r ON c.Id = r.Id
WHERE c.IdUser = '1234'
GROUP BY c.Id, c.Title, r.cnt

然而,' Id喜欢Linq等同于此请求,将其作为我的应用程序的数据访问层。

我尝试过类似的事情:

var qResult = from c in dbContext.TABLE_C
              join v in dbContext.TABLE_V on c.IdC equals v.IdC
              join r in dbContext.TABLE_R on v.IdC equals r.IdC into temp
              from x in temp.DefaultIfEmpty()
              group x by new { c.IdC, c.Title /*miss something ?*/} into grouped
              select new
              {
                  IdC = grouped.Key.IdC,          --good result
                  Title = grouped.Key.Title,      --good result
                  NbR = grouped.Distinct().Count(t => t.IdC > 0), --good, but "t.Id > 0" seems weird
                  Count = --I'm lost. No idea how to get my COUNT(...) properties (Nb_V1 and Nb_V2)
              };

我尝试调整this SO question,但我无法弄明白。我在分组子请求中迷失了Count 谁能解释我哪里错了?

专业提示:如果有人可以使用lambda表达式编写等效内容,则可获得奖励积分

1 个答案:

答案 0 :(得分:15)

将SQL转换为LINQ查询理解:

  1. 将子选择转换为单独声明的变量。
  2. 翻译LINQ子句中的每个子句,将monadic和aggregate运算符(DISTINCTTOPMINMAX等)转换为应用于整个LINQ查询的函数
  3. 使用表别名作为范围变量。使用列别名作为匿名类型字段名称。
  4. 对多个列使用匿名类型(new { ... })(例如,在groupby中)。
  5. 使用First().fieldgroupby聚合范围变量中获取非键值(例如,与MySQL一样)。
  6. JOIN条件不是AND的所有等式测试必须使用加入外的where子句或跨产品(from ... {来处理{1}} ...)然后from。如果您正在执行where,请在连接范围变量和LEFT JOIN调用之间添加lambda Where子句。
  7. DefaultIfEmpty()两个表之间多个JOIN ed等式测试的条件应该转换为匿名对象
  8. AND使用LEFT JOIN joinvariable 进行模拟,然后从{{1>} joinvariable 进行另一次<{1}}
  9. into替换为条件运算符(from)和.DefaultIfEmpty()测试。
  10. COALESCE转换为?:null转换为IN ... .Contains(),使用文字数组或数组变量作为常量列表。
  11. x NOT IN low ! high 翻译为 low {{1 } x Contains() x BETWEEN high
  12. AND翻译为三元条件运算符<=
  13. &&必须替换为select range_variable或者连接,一个包含所有范围变量的匿名对象。
  14. <=字段必须替换为CASE ... ?:,以创建包含所有所需字段或表达式的匿名对象。
  15. SELECT *翻译为C#三元条件运算符。
  16. 必须使用扩展方法处理正确的SELECT
  17. select new {翻译为},除非两个子查询都是IIF,在这种情况下,您可以翻译为FULL OUTER JOIN并取消UNION。< / LI>

    将这些规则应用于SQL查询,您将获得:

    Concat

    lambda翻译很棘手,但需要将DISTINCT转换为Union ... DISTINCT

    var subrq = from r in Table_R
                group r by r.Id into rg
                select new { Id = rg.Key, cnt = rg.Count() };
    
    var ansq = (from c in Table_C
                join v in Table_V on c.Id equals v.Id
                join r in subrq on c.Id equals r.Id into rj
                from r in rj.DefaultIfEmpty()
                where c.IdUser == "1234"
                group new { c, v, r } by new { c.Id, c.Title, r.cnt } into cvrg
                select new {
                    cvrg.Key.Title,
                    Nb_V2 = cvrg.Count(),
                    Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(),
                    Nb_R = (int?)cvrg.Key.cnt
                }).Distinct();