{"id":3447,"date":"2016-03-16T12:52:25","date_gmt":"2016-03-16T12:52:25","guid":{"rendered":"http:\/\/www.garysieling.com\/blog\/?p=3447"},"modified":"2016-03-16T12:52:25","modified_gmt":"2016-03-16T12:52:25","slug":"rethinkdb-full-outer-join-example","status":"publish","type":"post","link":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/","title":{"rendered":"RethinkDB: FULL OUTER JOIN example"},"content":{"rendered":"<p>If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point.<\/p>\n<p>The way to execute this correctly is to separate left and right joins, then combine and de-duplicate the results.<\/p>\n<p>In this case, we&#8217;ll do a full outer join of a list of users and audit history, which shows audit history without users, and users without history:<\/p>\n<pre lang=\"javascript\">\nr.db('test')\n .table('users')\n .outerJoin(\n    r.table('user_actions'),\n    (user, action) => \n      action('user_id').eq(user('id')))\n .zip()\n .union(\n    r.db('test')\n     .table('user_actions')\n     .outerJoin(\n       r.table('users'),\n       (action, user) => \n         action('user_id').eq(user('id'))\n ).zip()   \n)\n<\/pre>\n<p>Note that you need to apply &#8220;.zip&#8221; to both sides (or do it at the end). The two sides of the union are here also not at the same level, as they would be in SQL (the second is nested), so I suspect that there is an implicit ordering here, where the two sides of the union could be re-arranged in a SQL database.<\/p>\n<p>Another interesting point here is that in SQL, unions are sensitive to column ordering, but RethinkDB matches things on names in JSON, so you no longer have to deal with that irritation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;RethinkDB: FULL OUTER JOIN example&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[4],"tags":[160,462,466,523],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.9 - aioseo.com -->\n\t<meta name=\"description\" content=\"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"gary\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.9\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Gary Sieling - Software Engineer\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"RethinkDB: FULL OUTER JOIN example - Gary Sieling\" \/>\n\t\t<meta property=\"og:description\" content=\"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2016-03-16T12:52:25+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2016-03-16T12:52:25+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"RethinkDB: FULL OUTER JOIN example - Gary Sieling\" \/>\n\t\t<meta name=\"twitter:description\" content=\"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#blogposting\",\"name\":\"RethinkDB: FULL OUTER JOIN example - Gary Sieling\",\"headline\":\"RethinkDB: FULL OUTER JOIN example\",\"author\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\"},\"datePublished\":\"2016-03-16T12:52:25+00:00\",\"dateModified\":\"2016-03-16T12:52:25+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#webpage\"},\"articleSection\":\"Code Examples, databases, reql, rethinkdb, sql\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.garysieling.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"name\":\"Code Examples\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"position\":2,\"name\":\"Code Examples\",\"item\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#listItem\",\"name\":\"RethinkDB: FULL OUTER JOIN example\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#listItem\",\"position\":3,\"name\":\"RethinkDB: FULL OUTER JOIN example\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/category\\\/code-examples\\\/#listItem\",\"name\":\"Code Examples\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\",\"name\":\"Gary Sieling\",\"description\":\"Software Engineer\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/\",\"name\":\"gary\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/0be925276d848ffe98a6a9dc8cf33e67?s=96&d=identicon&r=g\",\"width\":96,\"height\":96,\"caption\":\"gary\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#webpage\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/\",\"name\":\"RethinkDB: FULL OUTER JOIN example - Gary Sieling\",\"description\":\"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/rethinkdb-full-outer-join-example\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/author\\\/gary\\\/#author\"},\"datePublished\":\"2016-03-16T12:52:25+00:00\",\"dateModified\":\"2016-03-16T12:52:25+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/\",\"name\":\"Gary Sieling\",\"description\":\"Software Engineer\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.garysieling.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"RethinkDB: FULL OUTER JOIN example - Gary Sieling","description":"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this","canonical_url":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#blogposting","name":"RethinkDB: FULL OUTER JOIN example - Gary Sieling","headline":"RethinkDB: FULL OUTER JOIN example","author":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"publisher":{"@id":"https:\/\/www.garysieling.com\/blog\/#organization"},"datePublished":"2016-03-16T12:52:25+00:00","dateModified":"2016-03-16T12:52:25+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#webpage"},"isPartOf":{"@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#webpage"},"articleSection":"Code Examples, databases, reql, rethinkdb, sql"},{"@type":"BreadcrumbList","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.garysieling.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","name":"Code Examples"}},{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","position":2,"name":"Code Examples","item":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#listItem","name":"RethinkDB: FULL OUTER JOIN example"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#listItem","position":3,"name":"RethinkDB: FULL OUTER JOIN example","previousItem":{"@type":"ListItem","@id":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/#listItem","name":"Code Examples"}}]},{"@type":"Organization","@id":"https:\/\/www.garysieling.com\/blog\/#organization","name":"Gary Sieling","description":"Software Engineer","url":"https:\/\/www.garysieling.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author","url":"https:\/\/www.garysieling.com\/blog\/author\/gary\/","name":"gary","image":{"@type":"ImageObject","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/0be925276d848ffe98a6a9dc8cf33e67?s=96&d=identicon&r=g","width":96,"height":96,"caption":"gary"}},{"@type":"WebPage","@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#webpage","url":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/","name":"RethinkDB: FULL OUTER JOIN example - Gary Sieling","description":"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.garysieling.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/#breadcrumblist"},"author":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"creator":{"@id":"https:\/\/www.garysieling.com\/blog\/author\/gary\/#author"},"datePublished":"2016-03-16T12:52:25+00:00","dateModified":"2016-03-16T12:52:25+00:00"},{"@type":"WebSite","@id":"https:\/\/www.garysieling.com\/blog\/#website","url":"https:\/\/www.garysieling.com\/blog\/","name":"Gary Sieling","description":"Software Engineer","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.garysieling.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Gary Sieling - Software Engineer","og:type":"article","og:title":"RethinkDB: FULL OUTER JOIN example - Gary Sieling","og:description":"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this","og:url":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/","article:published_time":"2016-03-16T12:52:25+00:00","article:modified_time":"2016-03-16T12:52:25+00:00","twitter:card":"summary_large_image","twitter:title":"RethinkDB: FULL OUTER JOIN example - Gary Sieling","twitter:description":"If you want to do a full outer join in RethinkDB you can, although it will be noticeably slower than other queries. If this seems strange, this is a somewhat common use case in reporting or scraping, where you may have a subset of all available fields at any point. The way to execute this"},"aioseo_meta_data":{"post_id":"3447","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"created":"2023-02-04 16:44:01","updated":"2026-07-06 01:38:53","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.garysieling.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/\" title=\"Code Examples\">Code Examples<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tRethinkDB: FULL OUTER JOIN example\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.garysieling.com\/blog"},{"label":"Code Examples","link":"https:\/\/www.garysieling.com\/blog\/category\/code-examples\/"},{"label":"RethinkDB: FULL OUTER JOIN example","link":"https:\/\/www.garysieling.com\/blog\/rethinkdb-full-outer-join-example\/"}],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts\/3447"}],"collection":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/comments?post=3447"}],"version-history":[{"count":0,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/posts\/3447\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/media?parent=3447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/categories?post=3447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.garysieling.com\/blog\/wp-json\/wp\/v2\/tags?post=3447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}