Skip to main content

full_outer_join

Lazy iterator implementations of a full outer join, inner join, and left and right joins of Python iterables.

This implements the sort-merge join, better known as the merge join, to join iterables in O(n) time with respect to the length of the longest iterable.

Note that the algorithm requires input to be sorted by the join key.

Example

(whitespace to make things explicit)

>>> list(full_outer_join.full_outer_join(
    [{"id": 1, "val": "foo"}                         ],
    [{"id": 1, "val": "bar"}, {"id": 2, "val": "baz"}],
    key=lambda x: x["id"]
))

[
    (1, ([{'id': 1, 'val': 'foo'}], [{'id': 1, 'val': 'bar'}])),
    (2, ([                       ], [{'id': 2, 'val': 'baz'}]))
]

To consume the output, your business logic might look like:

for group_key, key_batches in full_outer_join.full_outer_join(left, right):
    left_rows, right_rows = key_batches
    
    if left_rows and right_rows:
        # This is the inner join case.
        pass
    elif left_rows and not right_rows:
        # This is the left join case (no matching right rows)
        pass
    elif not left_rows and right_rows:
        # This is the right join case (no matching left rows)
        pass
    elif not left_rows and not right_rows:
        raise Exception("Unreachable")

Functions

name description
full_outer_join(*iterables, key=lambda x: x) Do a full outer join on any number of iterables, returning (key, (list[row], ...)) for each key across all iterables.
inner_join(*iterables, key=lambda x: x) Do an inner join across all iterables, returning (key, (list[row], ...)) for keys only in all iterables
left_join(left_iterable, right_iterable, key=lambda x: x) Do a left join on both iterables, returning keys for each unique key in left_iterable
right_join(left_iterable, right_iterable, key=lambda x: x) Do a right join on both iterables, returning keys for each unique key in right_iterable
cross_join(join_output, null=None) Do the cross (Cartesian) join on the output of full_outer_join or inner_join, yielding (key, (iter1_row, ...)) for each row. This is implemented for completeness and is probably not useful. Iterables lacking any rows for key are replaced with null in the output.

Why?

  1. Your input is already sorted and you don't want to consume your input iterators.
  2. Your business logic that consumes the joined output benefits from explicitly handling the match and no-match cases from each input iterable.
  3. You're insane. Your brain is irreparably broken by the relational model.

More examples

See test_insanity.py for a silly example of a SQL query hand-compiled into iterators.

Thanks

This was originally a PR to the more_itertools project who gave some excellent feedback on the design but ultimately did not want to merge it in.

Metadata

Release files for full-outer-join 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for full-outer-join 1.0.0
File Size Uploaded
full_outer_join-1.0.0.tar.gz 7.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for full-outer-join 1.0.0
File Interpreter ABI Platform
full_outer_join-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 13.2 kB

Release files / full_outer_join-1.0.0.tar.gz

Download URL full_outer_join-1.0.0.tar.gz
Size 7.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f8a22b73e6d30070f48522d2a01d56f64c6c0411d4468cc88854ce969c43e8e1
BLAKE2b-256 checksum
How to use checksums
fe02ff8350797577527ed7868070f8a689d7a3ad7a259f7752820f72d85edba9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.5

Release files / full_outer_join-1.0.0-py3-none-any.whl

Download URL full_outer_join-1.0.0-py3-none-any.whl
Size 5.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f5c02dc0b11f4380f6c5645c2737190c49e4e6e5b9fafec2ea01c72d367b92d8
BLAKE2b-256 checksum
How to use checksums
a70bf71655666bd21eec2256a3a9c265e5491d43f6697caf313b9795301256ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.5

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page