使用左联接转换LINQ内联接

时间:2018-11-20 16:19:20

标签: c# linq

我正在尝试在查询中实现左联接,此刻我得到的是“对象引用未设置为对象的实例”。

该查询作为内部联接工作正常,但是我希望包括左侧表中的所有行,即使找到匹配项也是如此。我尝试着遵循以前的一些文章,大多数都引用DefaultIfEmpty(),但是我没有弄清楚。

INNER JOIN - SQL
      SELECT TOP (1000) 
      FROM table1 as edc
      inner join table2 as c on edc.Id = c.Id
      inner join table3 as p on p.Id = c.Id
      group by p.Description

内部联接-SQL

  SELECT TOP (1000) 
  FROM table1 as edc
  inner join table2 as c on edc.Id = c.Id
  left join table3 as p on p.Id = c.Id
  group by p.Description

内部联接-LINQ

from edc in table1
   join q1 in table2 on __edc.Id equals q1__.Id
   join q2 in _table3 on q2.Id equals q1.Id 
   group q1 by q2.Description
   into grouped
   select new MyObj
   {
     Label = grouped.Key,
     Value = grouped.Count(),
    }

左联接-LINQ

from edc in table1
       join q1 in table2 on __edc.Id equals q1__.Id
       join q2 in _table3 on q2.Id equals q1.Id  into leftJoin
       from p in leftJoin.DefaultIfEmpty()
       group q1 by p.Description
       into grouped
       select new MyObj
       {
         Label = grouped.Key,
         Value = grouped.Count(),
        }

2 个答案:

答案 0 :(得分:0)

非常简单,只需将“从p”更改为“从q2”:

   from edc in table1
   join q1 in table2 on __edc.Id equals q1__.Id
   join q2 in _table3 on q2.Id equals q1.Id  into leftJoin
   from q2 in leftJoin.DefaultIfEmpty()
   group q1 by p.Description
   into grouped
   select new MyObj
   {
     Label = grouped.Key,
     Value = grouped.Count(),
    }

答案 1 :(得分:0)

请考虑以下示例。我们有3个表,其中table1和table2之间是左连接,table3是第二个左连接。您需要在两个联接上指定DefaultIfEmpty(),以包括右表中不匹配的行。

public class Item
{
    public int Id { get; set; }

    public string Description { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var table1 = new List<Item>
        {
            new Item {Id = 1, Description = "a"},
            new Item {Id = 2, Description = "b"},
            new Item {Id = 3, Description = "c"},
            new Item {Id = 4, Description = "d"}
        };

        var table2 = new List<Item>
        {
            new Item {Id = 1, Description = "e"},
            new Item {Id = 2, Description = "f"},
            new Item {Id = 4, Description = "g"}
        };

        var table3 = new List<Item>
        {
            new Item {Id = 1, Description = "h"},
            new Item {Id = 4, Description = "h"},
            new Item {Id = 5, Description = "i"},
            new Item {Id = 6, Description = "j"}
        };

        var leftJoin = from t1 in table1
            join t2 in table2 on t1.Id equals t2.Id into firstJoin
            from x in firstJoin.DefaultIfEmpty()
            join t3 in table3 on x?.Id equals t3.Id into secondJoin
            from y in secondJoin.DefaultIfEmpty()
            select new
            {
                Table1Id = t1?.Id,
                Table1Description = t1?.Description,
                Table2Id = x?.Id,
                Table2Description = x?.Description,
                Table3Id =  y?.Id,
                Table3Description = y?.Description
            };

        Console.WriteLine("Left Join:");
        foreach (var i in leftJoin)
        {
            Console.WriteLine($"T1Id: {i.Table1Id}, T1Desc: {i.Table1Description}, " +
                              $"T2Id: {i.Table2Id}, T2Desc: {i.Table2Description}, " +
                              $"T3Id: {i.Table3Id}, T3Desc: {i.Table3Description}");
        }
        Console.WriteLine(string.Empty);

        var grouped = from x in leftJoin
            group x by x.Table3Description
            into group1
            select new
            {
                Label = group1.Key,
                Count = group1.Count()
            };

        Console.WriteLine("Left Join Grouped:");
        foreach (var i in grouped)
        {
            Console.WriteLine($"Label: {i.Label}, Count: {i.Count}");
        }

        Console.ReadLine();
    }
}

运行程序将产生以下输出:

Left Join:
T1Id: 1, T1Desc: a, T2Id: 1, T2Desc: e, T3Id: 1, T3Desc: h
T1Id: 2, T1Desc: b, T2Id: 2, T2Desc: f, T3Id: , T3Desc:
T1Id: 3, T1Desc: c, T2Id: , T2Desc: , T3Id: , T3Desc:
T1Id: 4, T1Desc: d, T2Id: 4, T2Desc: g, T3Id: 4, T3Desc: h

Left Join Grouped:
Label: h, Count: 2
Label: , Count: 2

希望这会有所帮助!