Title: Unions and Outer Joins · Issue #264 · datajoint/datajoint-python · GitHub
Open Graph Title: Unions and Outer Joins · Issue #264 · datajoint/datajoint-python
X Title: Unions and Outer Joins · Issue #264 · datajoint/datajoint-python
Description: So far DataJoint has not offered the union operator and the outer join operators. These two operators are closely related. I propose to implement outer join/union as the + operator. Syntax a + b # full outer join of relations `a` and `b`...
Open Graph Description: So far DataJoint has not offered the union operator and the outer join operators. These two operators are closely related. I propose to implement outer join/union as the + operator. Syntax a + b # ...
X Description: So far DataJoint has not offered the union operator and the outer join operators. These two operators are closely related. I propose to implement outer join/union as the + operator. Syntax a + b # ...
Opengraph URL: https://github.com/datajoint/datajoint-python/issues/264
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Unions and Outer Joins","articleBody":"So far DataJoint has not offered the union operator and the outer join operators. These two operators are closely related. I propose to implement outer join/union as the `+` operator.\r\n\r\n## Syntax\r\n```python\r\na + b # full outer join of relations `a` and `b` \r\n```\r\nIncidentally, outer join is equivalent to union when the two arguments have the same sets of attributes. \r\n\r\nNote that MySQL does not implement full outer joins, so internally it will be implemented as a left join followed by a union with the right argument.\r\n\r\n## Rules \r\nThe full outer join follows the same rules as the join operator `a*b`:\r\n1. The primary key of the expression `a+b` is the union of the primary key attributes of `a` and `b`.\r\n1. The matching attributes in `a` and `b`, i.e. those sharing the same names in both relations must be of compatible datatypes and must belong to the primary key of either `a` or `b`. An exception will be raised if a non-key attribute with the same name is present in both relations. \r\n1. The order of attributes in the arguments does not matter and is not guaranteed in the result.\r\n\r\n## Equivalence to OUTER JOIN\r\n`a+b` is equivalent to the natural outer join operator in relational algebra. \r\n\r\n## Equivalence to SQL's UNION\r\n`a+b` is equivalent to relational union if `a` and `b` have the same sets of attributes. \r\n\r\n## Implementation of LEFT and RIGHT OUTER JOINs\r\nThe natural left join (`a NATURAL LEFT JOIN b`) can now be expressed as\r\n```python\r\na * b + a\r\n```\r\nor, equivalently, as\r\n```python\r\n(a + b) \u0026 a\r\n```\r\nor, equivalently, as\r\n```python\r\na + (b \u0026 a) \r\n```\r\nor, equivalently\r\n```python\r\n(a - b) + b\r\n``` \r\n\r\nIt is difficult to make DataJoint recognize all these patterns and to convert them into efficient SQL, so let's introduce the special syntax indicating left or right joins:\r\n\r\n```python\r\na * ~b # left outer join (all rows of `a` are kept).\r\n~a * b # right outer join (all rows of `b` are kept). \r\n~a * ~b # outer join (equivalent to `a+b`)\r\n```\r\n\r\nThe outer flag `~` survives projections and restrictions but not other operators:\r\n```python\r\n~(a \u0026 cond) * b # equivalent to (~a \u0026 cond) * b\r\n~a.proj() * b # equivalent to (~a).proj() * b\r\n```\r\n\r\n## Examples\r\n### Example 1: Simple union\r\nLet relation `a` with primary key (i, k) equal \r\n\r\n| *i \t| *k \t| \r\n|:-:\t|:-:\t|\r\n| 1\t| 1 \t|\r\n| 1\t| 2\t|\r\n| 2\t| 1 \t|\r\n\r\nLet relation `b` with primary key (k) equal \r\n\r\n| *k \t| i \t| \r\n|:-:\t|:-:\t|\r\n| 1\t| 1\t|\r\n| 2\t| 1\t|\r\n| 2\t| 3\t|\r\n\r\nThen `a+b` will be\r\n\r\n| *i \t| *k \t| \r\n|:-:\t|:-:\t|\r\n| 1\t| 1 \t|\r\n| 1\t| 2\t|\r\n| 2\t| 1 \t|\r\n| 3\t| 2 \t|\r\n\r\n### Example 2: No matching attributes: outer join = inner join\r\n\r\nLet relation `a` with primary key (i) equal \r\n\r\n| *i \t| m | \r\n|:-:\t|:-: |\r\n| 1\t| 6 |\r\n| 2\t| 6 \t|\r\n\r\nLet relation `b` with primary key (i, k) equal \r\n\r\n| *k \t| n | \r\n|:-:\t|:-: |\r\n| 1\t| 8 |\r\n| 2\t| 8 |\r\n\r\nThen `a+b` will be\r\n\r\n| *i \t| *k \t| m | n |\r\n|:-:\t|:-:\t|:-: |:-: |\r\n| 1\t| 1\t| 6 | 8 |\r\n| 1\t| 2\t| 6 | 8 |\r\n| 2\t| 1\t| 6 | 8 |\r\n| 2 | 2 | 6 | 8 |\r\n\r\n\r\n### Example 3: Simple outer join\r\n\r\nLet relation `a` with primary key (i) equal \r\n\r\n| *i \t| m | \r\n|:-:\t|:-: |\r\n| 1\t| 6 |\r\n| 2\t| 6 \t|\r\n| 3\t| 6 \t|\r\n\r\nLet relation `b` with primary key (i, k) equal \r\n\r\n| *i \t| *k \t| n | \r\n|:-:\t|:-:\t|:-: |\r\n| 1\t| 1\t| 8 |\r\n| 1\t| 2\t| 8 |\r\n| 2\t| 3\t| 8 |\r\n| 4 | 1 | 8 |\r\n\r\nThen `a+b` will be\r\n\r\n| *i \t| *k \t| m | n |\r\n|:-:\t|:-:\t|:-: |:-: |\r\n| 1\t| 1\t| 6 | 8 |\r\n| 1\t| 2\t| 6 | 8 |\r\n| 2\t| 3\t| 6 | 8 |\r\n| 4 | 1 | NULL | 8 |\r\n| 3 | NULL | 6 | NULL\r\n\r\nNote `a+b` may produce NULLs in the primary key. ","author":{"url":"https://github.com/dimitri-yatsenko","@type":"Person","name":"dimitri-yatsenko"},"datePublished":"2016-11-22T21:55:14.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/264/datajoint-python/issues/264"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:544af3b9-8be5-bbc2-70a6-93081ad2597c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9FEA:380AD5:F13732:1480D57:6A4D61D6 |
| html-safe-nonce | 5d51975e1a01f300b55dfba7ad6135873ff5831c38e9fbec32e043a19fc438cf |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5RkVBOjM4MEFENTpGMTM3MzI6MTQ4MEQ1Nzo2QTRENjFENiIsInZpc2l0b3JfaWQiOiI4MDU0NzY5MzE1MjQ3MTQ5NjYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | e68681e92a59553d99d4f484e5f8214203af298ab5027df975f56de5e013c61f |
| hovercard-subject-tag | issue:191134812 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/datajoint/datajoint-python/264/issue_layout |
| twitter:image | https://opengraph.githubassets.com/3ae655eec1215b0628ba0470bdcc0629b98b10b3f111f21777d0198d9d9f5e69/datajoint/datajoint-python/issues/264 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/3ae655eec1215b0628ba0470bdcc0629b98b10b3f111f21777d0198d9d9f5e69/datajoint/datajoint-python/issues/264 |
| og:image:alt | So far DataJoint has not offered the union operator and the outer join operators. These two operators are closely related. I propose to implement outer join/union as the + operator. Syntax a + b # ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | dimitri-yatsenko |
| hostname | github.com |
| expected-hostname | github.com |
| None | e6658d7c7808aeed776f841e0839b885fce343c9b96244be612c779298e7661e |
| turbo-cache-control | no-preview |
| go-import | github.com/datajoint/datajoint-python git https://github.com/datajoint/datajoint-python.git |
| octolytics-dimension-user_id | 2375501 |
| octolytics-dimension-user_login | datajoint |
| octolytics-dimension-repository_id | 5866704 |
| octolytics-dimension-repository_nwo | datajoint/datajoint-python |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 5866704 |
| octolytics-dimension-repository_network_root_nwo | datajoint/datajoint-python |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | a438513d3a22ffcd713795ed948c3e5525007665 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width