C#/LINQ

[C#]LINQ 왼쪽 조인(Left Join)

DevStory 2022. 8. 6.

왼쪽 조인이란?

왼쪽 조인(Left Join) 또는 왼쪽 외부 조인(Left Outer Join)은 두 번째 데이터 집합에 일치하는 데이터가 있는지 관계없이 첫 번째 데이터 집합의 모든 데이터가 반환되는 Join입니다.

 

예를 들어, 두 개의 데이터 집합(Employee, Department)이 존재합니다.

첫 번째 데이터 집합이 Employee인 경우

"나랑두" 사원의 부서 코드는 Department에 존재하지 않습니다. 하지만, 왼쪽 조인은 두 번째 데이터 집합인 Department에 일치하는 부서 코드가 없더라도 첫 번째 데이터 집합인 Employee의 모든 데이터가 반환되어야 합니다.

 

첫 번째 데이터 집합이 Department인 경우

이번에는 반대로 첫 번째 데이터 집합을 Department로 설정하고 두 번째 데이터 집합을 Employee로 설정합니다. 데이터 집합 Employee에는 부서 코드 4000, 5000인 사원이 존재하지 않습니다. 하지만, Department의 모든 데이터가 반환되어야 합니다.


Linq에서 Left Join

Linq에서는 Left Join 메서드와 연산자를 지원하지 않습니다. C#에서 Linq를 사용하여 Left Join을 구현하려면, DefaultIfEmpty() 메서드와 into 키워드를 사용해야 합니다.

 

DefaultIfEmpty() 메서드와 into 키워드를 사용하는 방법은 아래 예제를 통해 알아봅시다.


샘플 데이터

이번 포스팅에서는 사용자 정의 클래스인 Employee, Department 타입의 데이터 집합을 사용합니다.

[Employee 클래스]

public class Employee {
  public string Emp_Code { get; set; }  // 사원코드
  public string Emp_Name { get; set; }  // 사원명
  public string Dept_Code { get; set; } // 부서코드
  public static List<Employee> GetEmployees()
  {
    return new List<Employee>()
    {
      new Employee { Emp_Code = "1", Emp_Name = "홍길동", Dept_Code = "1000"},
      new Employee { Emp_Code = "2", Emp_Name = "호날두", Dept_Code = "1000"},
      new Employee { Emp_Code = "3", Emp_Name = "김첨지", Dept_Code = "2000"},
      new Employee { Emp_Code = "4", Emp_Name = "다람쥐", Dept_Code = "2000"},
      new Employee { Emp_Code = "5", Emp_Name = "나랑두", Dept_Code = "3000"}
    };
  }
}

[Department 클래스]

public class Department
{
  public string Dept_Code { get; set; } // 부서코드
  public string Dept_Name { get; set; } // 부서명
  public static List<Department> GetDeptments()
  {
    return new List<Department>()
    {
      new Department { Dept_Code = "1000", Dept_Name = "영업"},
      new Department { Dept_Code = "2000", Dept_Name = "기획"},
      new Department { Dept_Code = "4000", Dept_Name = "연구"},
      new Department { Dept_Code = "5000", Dept_Name = "분석"}
    };
  }
}


예제 1. 질의 구문

질의 구문에서 Left Join을 구현하려면 그룹 조인 결과에 대해 DefaultIfEmpty() 메서드를 호출해야 합니다.

 

순서 1.

첫 번째 단계로 그룹 조인을 수행합니다. Employee 리스트의 Dept_Code와 Department 리스트의 Dept_Code가 일치하는 데이터를 그룹화합니다.

from emp in Employee.GetEmployees()
join dept in Department.GetDeptments()
on   emp.Dept_Code equals dept.Dept_Code
into EmployeeDeptGroup

순서 2.

첫 번째 데이터 집합인 Employee 리스트가 두 번째 데이터 집합인 Department 리스트에 일치하는지 관계없이 항상 반환되어야 합니다. 그룹 조인 결과에 대해 DefaultIfEmpty() 메서드를 호출합니다.

from dept in EmployeeDeptGroup.DefaultIfEmpty()

DefaultIfEmpty() 메서드를 호출한 데이터 집합의 데이터가 비어 있으면, 기본 값을 가지는 컬렉션을 반환합니다. 즉, 첫 번째 단계에서 그룹화된 데이터가 없는 경우 기본 값을 가지는 컬렉션이 반환됩니다.

 

다음 소스 코드는 Employee 리스트를 기준으로 Department 리스트를 Left Join 합니다.

class Program
{
  static void Main(string[] args)
  {
    var LeftJoinQuerydResult = from emp in Employee.GetEmployees()
                               join dept in Department.GetDeptments()
                               on   emp.Dept_Code equals dept.Dept_Code
                               into EmployeeDeptGroup
                               from dept in EmployeeDeptGroup.DefaultIfEmpty()
                               select new { emp, dept };

    foreach (var item in LeftJoinQuerydResult)
    {
      Console.WriteLine("사원명 : " + item.emp.Emp_Name + " , 부서명 : " + item.dept?.Dept_Name);
    }
  }
}

[실행 결과]

사원명 : 홍길동 , 부서명 : 영업
사원명 : 호날두 , 부서명 : 영업
사원명 : 김첨지 , 부서명 : 기획
사원명 : 다람쥐 , 부서명 : 기획
사원명 : 나랑두 , 부서명 :

예제 2. 메서드 구문

메서드 구문에서 Left Join을 구현하려면, GroupJoin() 메서드 결과에 대해 SelectMany() 메서드와 DefaultIfEmpty() 메서드를 호출합니다.

class Program
{
  static void Main(string[] args)
  {
    var LeftJoinMethodResult = Employee.GetEmployees()
        .GroupJoin(
        Department.GetDeptments(),
        emp => emp.Dept_Code,
        dept => dept.Dept_Code,
        (emp, dept) => new { emp, dept })
        .SelectMany(
        item => item.dept.DefaultIfEmpty(),
        (employee, department) => new { employee, department });

    foreach (var item in LeftJoinMethodResult)
    {
      Console.WriteLine("사원명 : " + item.employee.emp.Emp_Name + " , 부서명 : " + item.department?.Dept_Name);
    }
  }
}

[실행 결과]

사원명 : 홍길동 , 부서명 : 영업
사원명 : 호날두 , 부서명 : 영업
사원명 : 김첨지 , 부서명 : 기획
사원명 : 다람쥐 , 부서명 : 기획
사원명 : 나랑두 , 부서명 :
반응형

댓글