SELECT * from MASTER m
LEFT JOIN CHILD C
ON m.ID=C.MASTER_ID
WHERE C.MASTER_ID is null
所以,通常这会返回Master没有孩子的所有记录。我发现了.DefualtIfEmpty(),但这并没有消除有孩子的主记录。
我从以下几行开始:
var recs=from m in MASTER
from c in child
.where (mapping=>mapping.MasterId == m.Id)
.DefaultIfEmpty()
select new { MasterId = m.Id};
但就我而言,这就是卡住了。我假设.DefaultIfEmpty()不是我正在寻找的东西。 注意:主表中有几百万行。孩子们接近同样的数量。我只提到因为它不会有效地撤回所有记录等。理想情况下,生成的SQL看起来就像我发布的SQL。
全部谢谢。
答案 0 :(得分:3)
如果您使用的是EF,那么您可以使用代表孩子的导航属性来获取不会生孩子的主人:
var result= from m in MASTER
where m.Children.Count()==0// or m.Any()
select m;
如果你想在linq中使用显式连接来做,你可以试试这个:
var recs=from m in MASTER
join c in child on m.Id equals C.MasterId into gj
where gj.Count()==0 // or gj.Any()
select m;
答案 1 :(得分:1)
这将为您提供所有没有孩子的主记录。
var recs = MASTER.Where(x => !child.Any(y => m.Id == c.MasterId));
!Any
将生成一个not Exists
SQL语句,该语句将被转换为执行计划中的anti semi join
,这是此类检查的最佳结果。
答案 2 :(得分:0)
您可以使用Linq执行左外部联接
var leftJoinResult = from m in MASTER join c in CHILD
on m.ID equals C.MASTER_ID
into a
from b in a.DefaultIfEmpty()
select new {MASTER = m,
CHILD = b};
然后消除有孩子的主记录
var result=leftJoinResult.where(x=>x.CHILD == null).select(y=>y.MASTER).ToList();
答案 3 :(得分:0)
我有同样的问题。仅当您的孩子中至少有一行时,此解决方案才有效。行的ID无关紧要。
var recs=from m in MASTER
from c in child
.where (mapping=>mapping.MasterId == m.Id)
.DefaultIfEmpty() into fullC
select new { MasterId = m.Id};
将关键字 into 变成魔术。添加它会显示所有行,以及那些在c中具有NULL值的行。
答案 4 :(得分:0)
我现在遇到了这个问题,必须使用简洁的 SQL 并使其以非常优化的方式工作。
林克:
var recs=from m in MASTER
from c in child.where (mapping=>mapping.MasterId == m.Id).DefaultIfEmpty()
where c.Id == null //Compiler creates a warning because int will never be null, but it works and creates outer left join
select new { MasterId = m.Id};
结果 SQL:
SELECT
"Extent1"."Id" AS "MasterId"
FROM "DBO"."Master" "Extent1"
LEFT OUTER JOIN "DBO"."Child" "Extent2" ON "Extent2"."MasterId" = "Extent1"."Id"
WHERE ("Extent2"."Id" IS NULL)
如果您有多个连接条件,这也适用 并且还为多个左连接工作
ps。我将 EF 与 Oracle 一起使用,因此不确定这在 EF 的 SQLServer 提供程序上是否会略有不同。