{"id":4723,"date":"2008-02-12T11:47:00","date_gmt":"2008-02-12T11:47:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2008\/02\/12\/converting-sql-to-linq-part-9-full-outer-join-bill-horst\/"},"modified":"2024-07-05T14:33:26","modified_gmt":"2024-07-05T21:33:26","slug":"converting-sql-to-linq-part-9-full-outer-join-bill-horst","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/converting-sql-to-linq-part-9-full-outer-join-bill-horst\/","title":{"rendered":"Converting SQL to LINQ, Part 9: Full Outer Join (Bill Horst)"},"content":{"rendered":"<p class=\"MsoNoSpacing\"><span>This post assumes you&rsquo;ve read the <a class=\"\" title=\"previous posts\" href=\"http:\/\/blogs.msdn.com\/vbteam\/archive\/tags\/Converting+SQL+to+LINQ\/default.aspx\">previous posts<\/a> in this series.<span>&nbsp; <\/span>It makes the same assumptions as Part 8, and I will pick up where I left off, covering Full Outer Join.<span>&nbsp; <\/span>Once again, I recognize this isn&rsquo;t an ideal situation, so if you&rsquo;d like to see better support of Full Outer Join in a future VB release, you can file a suggestion from our <a class=\"\" title=\"product feedback\" href=\"http:\/\/connect.microsoft.com\/feedback\/default.aspx?SiteID=210\">product feedback<\/a> site.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>A Full Outer Join is basically like the union of the results of a Left Outer Join and Right Outer Join.<span>&nbsp; <\/span>Records are joined together based on common fields, and all records with no match are also displayed, whether in the &ldquo;left&rdquo; or &ldquo;right&rdquo; table.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>SQL<\/p>\n<p><\/span><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><span>SELECT Contact.ContactName, Shipment.OrderDate<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>FROM CustomerTable Contact<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>FULL OUTER JOIN OrderTable Shipment<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><span>&nbsp;&nbsp; <\/span>ON Contact.CustomerID = Shipment.CustomerID<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Using the same data as my last post, this query would give me results like the following:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><span>Results:<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>ContactName<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>OrderDate<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNoSpacing\"><span>John Doe<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NULL<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Bill Horst<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>3\/25\/1982<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Bill Horst<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>3\/13\/2005<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Jane Doe<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>9\/29\/2007<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>NULL<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>1\/31\/2008<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Like Left and Right Join, Full Outer Join is not supported directly with LINQ, but you can write a query to produce the same results.<span>&nbsp; <\/span>Currently, the simplest way to do this is to concatenate three subqueries together.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>The first query provides the results where the &ldquo;right&rdquo; table has a null value.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>VB<\/p>\n<p><\/span><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNormal\"><span>From<\/span><span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Group<\/span><span> <span>Join<\/span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span>Into<\/span><span> HaveMatch = Any() _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Where<\/span><span> <span>Not<\/span> HaveMatch _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Select<\/span><span> Contact.ContactName, OrderDate = NothingDate<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Results:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;John Doe&#8221;, OrderDate = Nothing}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>The second query provides the results of an Inner Join.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>VB<\/p>\n<p><\/span><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNormal\"><span>From<\/span><span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Join<\/span><span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Select<\/span><span> Contact.ContactName, Shipment.OrderDate<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Results:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Bill Horst&#8221;, OrderDate = #3\/25\/1982#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Bill Horst&#8221;, OrderDate = #3\/13\/2005#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Jane Doe&#8221;, OrderDate = #9\/29\/2007#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>The third query provides the results where the &ldquo;left&rdquo; table has a null value.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>VB<\/p>\n<p><\/span><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNormal\"><span>From<\/span><span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Group<\/span><span> <span>Join<\/span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp; <\/span><span>Into<\/span> HaveMatch = Any() _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Where<\/span><span> <span>Not<\/span> HaveMatch _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Select<\/span><span> ContactName = NothingString, Shipment.OrderDate<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Results:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = Nothing, OrderDate = #1\/31\/2008#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>When the results are put together, we get a full outer join.<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<table class=\"MsoTableGrid\" cellspacing=\"0\" cellpadding=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNoSpacing\"><b><span>VB<\/p>\n<p><\/span><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"top\" width=\"638\">\n<p class=\"MsoNormal\"><span>(<span>From<\/span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>Group<\/span> <span>Join<\/span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp; <\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp; <\/span><span>Into<\/span> HaveMatch = Any() _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>Where<\/span> <span>Not<\/span> HaveMatch _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span><span>Select<\/span> Contact.ContactName, OrderDate = NothingDate) _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;<\/span>.Concat(<span>From<\/span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Join<\/span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;<\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Select<\/span> Contact.ContactName, Shipment.OrderDate) _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>.Concat(<span>From<\/span> Shipment <span>In<\/span> OrderTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>Group<\/span> <span>Join<\/span> Contact <span>In<\/span> CustomerTable _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>On<\/span> Contact.CustomerID <span>Equals<\/span> Shipment.CustomerID _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Into<\/span> HaveMatch = Any() _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Where<\/span> <span>Not<\/span> HaveMatch _<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Select<\/span> ContactName = NothingString, Shipment.OrderDate)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Results:<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;John Doe&#8221;, OrderDate = Nothing}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Bill Horst&#8221;, OrderDate = #3\/25\/1982#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Bill Horst&#8221;, OrderDate = #3\/13\/2005#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = &#8220;Jane Doe&#8221;, OrderDate = #9\/29\/2007#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>{ContactName = Nothing, OrderDate = #1\/31\/2008#}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoNoSpacing\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNoSpacing\"><span>Hopefully this is helpful to some.<span>&nbsp; <\/span>As noted above, I realize this is not an ideal way to implement a Full Outer Join.<span>&nbsp; <\/span>If you&rsquo;d like to see support for a Full Outer Join with simple syntax in a future VB release, please file a suggestion from our <a class=\"\" title=\"product feedback\" href=\"http:\/\/connect.microsoft.com\/feedback\/default.aspx?SiteID=210\">product feedback<\/a> <\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post assumes you&rsquo;ve read the previous posts in this series.&nbsp; It makes the same assumptions as Part 8, and I will pick up where I left off, covering Full Outer Join.&nbsp; Once again, I recognize this isn&rsquo;t an ideal situation, so if you&rsquo;d like to see better support of Full Outer Join in a [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[20,195],"tags":[41,49,94,166],"class_list":["post-4723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-converting-sql-to-linq","category-visual-basic","tag-bill-horst","tag-converting-sql-to-linq","tag-linqvb9","tag-vb2008"],"acf":[],"blog_post_summary":"<p>This post assumes you&rsquo;ve read the previous posts in this series.&nbsp; It makes the same assumptions as Part 8, and I will pick up where I left off, covering Full Outer Join.&nbsp; Once again, I recognize this isn&rsquo;t an ideal situation, so if you&rsquo;d like to see better support of Full Outer Join in a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=4723"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/4723\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=4723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=4723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=4723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}