我用多个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表达式编写等效内容,则可获得奖励积分
答案 0 :(得分:15)
将SQL转换为LINQ查询理解:
DISTINCT
,TOP
,MIN
,MAX
等)转换为应用于整个LINQ查询的函数new {
... }
)(例如,在groupby
中)。First().field
从groupby
聚合范围变量中获取非键值(例如,与MySQL一样)。JOIN
条件不是AND
的所有等式测试必须使用加入外的where
子句或跨产品(from
... {来处理{1}} ...)然后from
。如果您正在执行where
,请在连接范围变量和LEFT JOIN
调用之间添加lambda Where
子句。DefaultIfEmpty()
两个表之间多个JOIN
ed等式测试的条件应该转换为匿名对象AND
使用LEFT JOIN
joinvariable 进行模拟,然后从{{1>} joinvariable 进行另一次<{1}} into
替换为条件运算符(from
)和.DefaultIfEmpty()
测试。COALESCE
转换为?:
和null
转换为IN
... .Contains()
,使用文字数组或数组变量作为常量列表。NOT IN
low !
high 翻译为 low {{1 } x Contains()
x BETWEEN
high 。AND
翻译为三元条件运算符<=
。&&
必须替换为select range_variable或者连接,一个包含所有范围变量的匿名对象。<=
字段必须替换为CASE
... ?:
,以创建包含所有所需字段或表达式的匿名对象。SELECT *
翻译为C#三元条件运算符。SELECT
。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();