Linq Left Join其中right为null

时间:2016-10-13 13:56:21

标签: c# .net linq linq-to-sql

来自SQL的linq相对较新。所以,我试图找出以下的左连接:

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。

全部谢谢。

5 个答案:

答案 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 提供程序上是否会略有不同。