This documentation page is also available as an interactive notebook. You can launch the notebook in
Kaggle or Colab, or download it for use with an IDE or local Jupyter installation, by clicking one of the
above links.
Combine data from multiple tables using inner, left, and cross joins.
Problem
You have related data in separate tables and need to combine them for
analysis—customers with orders, products with inventory, or media with
metadata.
Solution
What’s in this recipe:
- Inner join to match rows from both tables
- Left join to keep all rows from the first table
- Cross join for Cartesian product (all combinations)
- Join with filtering, aggregation, and saving results
- Paginate results with
limit() and offset
Use table1.join(table2, on=..., how=...) to combine tables based on
matching columns.
Setup
Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata
Created directory ‘join_demo’.
<pixeltable.catalog.dir.Dir at 0x148e73850>
Create sample tables
Created table ‘customers’.
Inserted 3 rows with 0 errors in 0.01 s (385.68 rows/s)
Created table ‘orders’.
Inserted 4 rows with 0 errors in 0.01 s (657.81 rows/s)
Inner join (matching rows only)
Left join (keep all from first table)
Join with filtering
Join with aggregation
Cross join (all combinations)
Created table ‘products’.
Inserted 2 rows with 0 errors in 0.00 s (422.52 rows/s)
Save join results to a new table
Created table ‘orders_report’.
Inserted 3 rows with 0 errors in 0.01 s (500.32 rows/s)
Paginate results with limit and offset
Use limit(n, offset=k) to retrieve results in pages. This is useful
for displaying results incrementally or building paginated APIs.
Explanation
Join types:
Join syntax:
Aggregation functions:
Saving join results:
Pagination:
Tips:
- Use explicit predicates (
t1.col == t2.col) for clarity
- Chain
.where() after join to filter results
- Chain
.group_by() for aggregations
- Use
'left' join when the first table is your “main” table
- Use named columns in
.select(name=col) for clean column names
- Always use
.order_by() with pagination to get deterministic page
ordering
See also