use*_*153 3 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
Run Code Online (Sandbox Code Playgroud)
但是,'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)
};
Run Code Online (Sandbox Code Playgroud)
我试图适应这个问题,但我无法弄清楚.我迷失Count了分组子请求的内部.
谁能解释我哪里错了?
专业提示:如果有人可以使用lambda表达式编写等效内容,则可获得奖励积分
Net*_*age 20
用于将SQL转换为LINQ查询理解:
DISTINCT,TOP,MIN,MAX等等)转换成适用于整个LINQ查询功能.new {... })(例如groupby).First().field从groupby聚合范围变量中获取非键值(例如,与MySQL一样).JOIN那是不是所有的平等与测试条件AND必须用处理equals条款之外的加入,或跨产品(JOIN... AND...),然后where.如果您这样做from,请from在连接范围变量和where调用之间添加lambda 子句.LEFT JOINWhere应将两个表之间的多个ed相等测试条件转换为匿名对象DefaultIfEmpty()通过使用模拟LEFT JOIN joinvariable做一套从into该joinvariable其次from..DefaultIfEmpty()为条件运算符(COALESCE)和?:测试.null来IN和.Contains()到NOT IN... !,使用文字数组或数组变量恒定名单.Contains() 低 BETWEEN 高到低 AND X <= X && 高.<=为三元条件运算符CASE.IIF 必须替换为select range_variable或者连接,包含所有范围变量的匿名对象.?:字段必须替换为SELECT *... SELECT创建一个包含所有所需字段或表达式的匿名对象.select new {为C#三元条件运算符.}必须使用扩展方法处理正确的.将这些规则应用于SQL查询,您将获得:
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();
Run Code Online (Sandbox Code Playgroud)
lambda翻译很棘手,但转换SELECT为let... FULL OUTER JOIN是需要的:
var subr2 = Table_R.GroupBy(r => r.Id).Select(rg => new { Id = rg.Key, cnt = rg.Count() });
var ans2 = Table_C.Where(c => c.IdUser == "1234")
.Join(Table_V, c => c.Id, v => v.Id, (c, v) => new { c, v })
.GroupJoin(subr, cv => cv.c.Id, r => r.Id, (cv, rj) => new { cv.c, cv.v, rj })
.SelectMany(cvrj => cvrj.rj.DefaultIfEmpty(), (cvrj, r) => new { cvrj.c, cvrj.v, r })
.GroupBy(cvr => new { cvr.c.Id, cvr.c.Title, cvr.r.cnt })
.Select(cvrg => new { cvrg.Key.Title, Nb_V2 = cvrg.Count(), Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(), Nb_R = (int?)cvrg.Key.cnt });
Run Code Online (Sandbox Code Playgroud)