LINQ – Group Join và Outer Join (Left Join, Right Join)

Bằng cách kết hợp join và into, ta có thể kết nhiều tập dữ liệu và kết quả trả về sẽ được nằm trong một cấu trúc phân cấp tương tự như GroupBy. Một đặc điểm của Group Join là tập dữ liệu bên trái sẽ được lấy tất cả, không quan tâm chúng có được so khớp trùng với tập dữ liệu bên phải hay không. Từ đó, ta có thể áp dụng để thực hiện outer join với LINQ.

Group Join

Như các bài viết trước tôi cung cấp một ví quen thuộc sau:

class Product
{
	public int ProductID;
	public string ProductName;
	public int CategoryID;

	public Product(int id, string name, int categoryId)
	{
		this.ProductID=id;
		this.ProductName=name;
		this.CategoryID=categoryId;
	}
}
class Category
{
	public int CategoryID;
	public string CategoryName;

	public Category(int id, string name)
	{
		this.CategoryID=id;
		this.CategoryName=name;
	}
}

// ...
var products=new Product[]{
	new Product(1,"PowerPoint",100),
	new Product(2,"Excel",100),
	new Product(3,"Photoshop",101),
	new Product(4,"TuneUp",105),
};
var categories=new Category[]{
	new Category(100,"Microsoft"),
	new Category(101,"Adobe"),
	new Category(102,"Sun")
};

Ví dụ sau sẽ xuất ra một bảng phân loại sản phẩm theo category trong LINQPAD:

from p in products
		join c in categories on p.CategoryID equals c.CategoryID into catGroup
		from cat in catGroup
		select new
		{
			Category=cat.CategoryName,
			Products=p
		}
IEnumerable<> (3 items)
Category Products
Microsoft
Product
UserQuery+Product
ProductID 1
ProductName PowerPoint
CategoryID 100
Microsoft
Product
UserQuery+Product
ProductID 2
ProductName Excel
CategoryID 100
Adobe
Product
UserQuery+Product
ProductID 3
ProductName Photoshop
CategoryID 101

Outer Join:Left Join và Right Join

Vận dụng Group Join, bạn có thể thực hiện các phép kết Outer Join. Để thực hiện điều này, ta dùng extension method DefaultIfEmpy() của LINQ. Phương thức này sẽ lấy giá trị mặc định nếu như dữ liệu là rỗng. Trong trường hợp này giá trị mặc định đó sẽ là null. Left Join được minh họa như hình dưới đây với vùng được tô màu là phần dữ liệu trả về sau khi thực hiện:

Trong câu truy vấn bạn cũng cần phải kiểm tra trường hợp dữ liệu bằng null để xử lý thích hợp. Ví dụ sau thực hiện left join với products và categories, để thực hiện right join,  bạn chỉ cần đổi thứ tự hai tập hợp lại:

Query Syntax:

from p in products
		join c in categories on p.CategoryID equals c.CategoryID into catGroup
		from cat in catGroup.DefaultIfEmpty()
		select new
		{
			Category=cat==null?"<null>":cat.CategoryName,
			Product=p.ProductName
		}

Method Syntax:

products
   .GroupJoin (
      categories,
      p => p.CategoryID,
      c =>c.CategoryID,
      (p, catGroup) =>
         new
         {
            p = p,
            catGroup = catGroup
         }
   )
   .SelectMany (
      temp0 => temp0.catGroup.DefaultIfEmpty (),
      (temp0, cat) =>
         new
         {
            Category = (cat == null) ? "<null>" : cat.CategoryName,
            Product = temp0.p.ProductName
         }
   )

Kết quả:

IEnumerable<> (4 items)
Category Product
Microsoft PowerPoint
Microsoft Excel
Adobe Photoshop
<null> TuneUp

https://yinyangit.wordpress.com

Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s