Ngôn ngữ LINQ - Toán tử Inner Join

Toán tử Inner Join trong LINQ

Các toán tử Join ghép nối hai danh sách và tạo ra một kết quả mới. Bảng sau liệt kê các toán tử Join có sẵn trong LINQ:

Toán tử Mô tả
Join Toán tử Join ghép nối hai danh sách dựa trên một khóa và trả về danh sách kết quả. Nó giống như INNER JOIN của SQL.
GroupJoin Toán tử GroupJoin ghép nối hai danh sách dựa trên các khóa và trả về các nhóm danh sách. Nó giống như LEFT OUTER JOIN của SQL.

Toán tử Join là một trong những toán tử truy vấn chuẩn của LINQ.

Toán tử Join trong LINQ

Toán tử Join hoạt động trên hai danh sách, danh sách bên trong và danh sách bên ngoài. Nó trả về một danh sách mới chứa các phần tử từ cả hai danh sách thỏa mãn biểu thức đã chỉ định. Nó giống như INNER JOIN của SQL.

Phương thức Join trong Cú pháp phương thức

Phương thức mở rộng Join có hai phương thức quá tải như dưới đây.


public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, 
            IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, 
            Func<TInner, TKey> innerKeySelector, 
            Func<TOuter, TInner, TResult> resultSelector);

public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, 
            IEnumerable<TInner> inner, 
            Func<TOuter, TKey> outerKeySelector,
            Func<TInner, TKey> innerKeySelector, 
            Func<TOuter, TInner, TResult> resultSelector,
            IEqualityComparer<TKey> comparer);

Ví dụ sau đây join hai danh sách kiểu chuỗi và trả về danh sách mới bao gồm các chuỗi tương ứng trong cả hai danh sách.

IList<string> strList1 = new List<string>() 
{ 
    "One", 
    "Two", 
    "Three", 
    "Four"
};

IList<string> strList2 = new List<string>() 
{ 
    "One", 
    "Two", 
    "Five", 
    "Six"
};

var innerJoin = strList1.Join(strList2,
    str1 => str1, 
    str2 => str2, 
    (str1, str2) => str1);
    
foreach (var str in innerJoin )			
    Console.WriteLine(str);

Đây là kết quả khi biên dịch và thực thi chương trình:

One 
Two

Xem ví dụ

Bây giờ, hãy hiểu phương thức Join bằng cách sử dụng lớp Student Standard trong đó lớp Student có thuộc tính StandardID tương ứng với thuộc tính StandardID của lớp Standard.

public class Student
{ 
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public int Age { get; set; }
    public int StandardID { get; set; }
}

public class Standard
{ 
    public int StandardID { get; set; }
    public string StandardName { get; set; }
}

Ví dụ sau đây min họa sử dụng phương thức Join trong cú pháp phương thức LINQ.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21, StandardID = 1 } ,
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18, StandardID = 2 } ,
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20, StandardID = 2 } ,
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

IList<Standard> standardList = new List<Standard>() 
{ 
    new Standard(){ StandardID = 1, StandardName="Standard 1"},
    new Standard(){ StandardID = 2, StandardName="Standard 2"},
    new Standard(){ StandardID = 3, StandardName="Standard 3"}
};

var innerJoinResult = studentList.Join(// outer sequence 
    standardList,  // inner sequence 
    student => student.StandardID,    // outerKeySelector
    standard => standard.StandardID,  // innerKeySelector
    (student, standard) => new  // result selector
        {
            StudentName = student.StudentName,
            StandardName = standard.StandardName
        });

foreach (var obj in innerJoinResult)
{    
    Console.WriteLine("{0} - {1}", obj.StudentName, obj.StandardName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

John - Standard 1
Steve - Standard 1
Bill - Standard 2
Ram - Standard 2

Xem ví dụ


Hình ảnh sau đây minh họa các phần của phương thức mở rộng Join trong ví dụ trên.

Phương thức mở rộng Join trong LINQ

Trong ví dụ trên về truy vấn nối, studentList là danh sách bên ngoài vì truy vấn bắt đầu từ nó. Tham số đầu tiên trong phương thức Join được sử dụng để xác định danh sách bên trong là StandardList trong ví dụ trên.

Tham số thứ hai và thứ ba của phương thức Join được sử dụng để chỉ định trường có giá trị khớp với biểu thức lambda để đưa phần tử vào kết quả.

Biểu thức student => student.StandardID lấy trường StandardID của từng phần tử trong studentList làm khóa.

Biểu thức standard => standard.StandardID lấy trường StandardID của từng phần tử trong standardList làm khóa

Nếu giá trị của cả hai khóa này khớp với nhau thì phần tử đó được đưa vào danh sách kết quả.

Tham số cuối cùng trong phương thức Join là một biểu thức để tạo kết quả. Trong ví dụ trên, kết quả trả về là một kiểu ẩn danh bao gồm thuộc tính StudentName và StandardName của cả hai danh sách.

Khóa StandardID của cả hai danh sách phải khớp thì mới được đưa vào kết quả, ngược lại thì sẽ không được đưa vào kết quả. Ví dụ: sinh viên Ron không được liên kết với bất kỳ Standard nào nên sinh viên Ron không được thêm vào kết quả.


Mệnh đề join trong cú pháp truy vấn LINQ

Toán tử join trong cú pháp truy vấn hoạt động hơi khác so với cú pháp phương thức. Nó đòi hỏi danh sách bên ngoài, danh sách bên trong, bộ chọn khóa và bộ chọn kết quả.

Từ khóa on được sử dụng cho bộ chọn khóa trong đó phía bên trái của toán tử equals là khóa của danh sách bên ngoài (outerKey) và bên phải của nó là khóa của danh sách bên trong (innerKey).

Dưới đây là cú pháp của mệnh đề join trong cú pháp truy vấn LINQ.

from ... in outerSequence

join ... in innerSequence on outerKey equals innerKey

select ...

Ví dụ sau đây về toán tử join trong cú pháp truy vấn trả về một tập hợp các phần tử từ studentList và standardList nếu hai thuộc tính Student.StandardIDStandard.StandardID của chúng khớp nhau.

// Student collection
IList<Student> studentList = new List<Student>() 
{ 
    new Student() { StudentID = 1, StudentName = "John", Age = 18, StandardID = 1 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21, StandardID = 1 } ,
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18, StandardID = 2 } ,
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20, StandardID = 2 } ,
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

IList<Standard> standardList = new List<Standard>() 
{ 
    new Standard(){ StandardID = 1, StandardName="Standard 1"},
    new Standard(){ StandardID = 2, StandardName="Standard 2"},
    new Standard(){ StandardID = 3, StandardName="Standard 3"}
};

var innerJoinResult = from s in studentList // outer sequence
                      join st in standardList //inner sequence 
                          on s.StandardID equals st.StandardID // key selector 
                      select new 
					  { // result selector 
                          StudentName = s.StudentName, 
                          StandardName = st.StandardName 
                      };

foreach (var obj in innerJoinResult)
{    
    Console.WriteLine("{0} - {1}", obj.StudentName, obj.StandardName);
}

Đây là kết quả khi biên dịch và thực thi chương trình:

John - Standard 1
Steve - Standard 1
Bill - Standard 2
Ram - Standard 2

Xem ví dụ


 Lưu ý: Sử dụng toán tử equals để khớp với bộ chọn khóa. Toán tử == không hợp lệ.

Những điểm cần nhớ về toán tử Join trong LINQ

  1. JoinGroupJoin là các toán tử ghép nối.
  2. Join giống như INNER JOIN của SQL. Nó trả về một danh sách mới chứa các phần tử khớp khóa từ hai danh sách.
  3. Toán tử Join ghép nối danh sách bên trong và danh sách bên ngoài và tạo ra một danh sách kết quả.
  4. Cú pháp truy vấn Join :
    from... in outerSequence
    join... in innerSequence 
    on  outerKey equals innerKey
    select ...