Skip to main content
Puri can join multiple tables to query related data together. This document explains INNER JOIN, LEFT JOIN, and complex join patterns.

Join Overview

INNER JOIN

Data existing in both tables join()

LEFT JOIN

Left table based, right is Optional leftJoin()

Self JOIN

Join same table Using alias

M:N JOIN

Many-to-many relationship join Using junction table

INNER JOIN

Queries only data that exists in both tables.

Basic JOIN

When to use INNER JOIN: - When the relationship is required (NOT NULL foreign key) - When data must exist in both tables - Example: employees β†’ users (all employees must have a user account)

Multiple Table JOIN

LEFT JOIN

Includes all data from the left table, and includes if available from the right table.

Basic LEFT JOIN

When to use LEFT JOIN: - When the relationship is optional (NULLABLE foreign key) - When all data from the left table is needed - Example: employees β†’ departments (some employees may not have a department)

INNER JOIN vs LEFT JOIN Comparison

Complex LEFT JOIN

Mixed INNER + LEFT JOIN

Use INNER JOIN for required relationships, LEFT JOIN for optional ones.
Join type selection guide: 1. Check database schema (NOT NULL vs NULLABLE) 2. NOT NULL foreign key β†’ INNER JOIN 3. NULLABLE foreign key β†’ LEFT JOIN 4. Consider business requirements

Reusing an Existing JOIN

Use ensureJoin() or ensureLeftJoin() when a Model adds a JOIN that may already have been added by a Subset query.
Puri compares JOINs by alias. If the alias, table, JOIN type, left column, and right column all match, it reuses the existing JOIN. If the alias is new, it adds the JOIN. Reusing an alias with a different definition throws an error before SQL execution. The same physical table can still be joined more than once under different aliases.
ensureJoin() and ensureLeftJoin() support simple column equality JOINs against tables. Callback and subquery JOINs continue to use join() and leftJoin() and are not considered reusable.

Self JOIN - Self Reference

Use aliases when joining the same table.

Department Hierarchy Example

Example Results:

User Referrer Example

Many-to-Many Join

Many-to-many (M:N) relationships are joined through junction tables.

Projects ↔ Employees Example

Result characteristics:
  • 1 project with N employees β†’ N rows
  • Projects without employees β†’ 1 row (employee fields are null)
M:N join considerations: 1. Results are duplicated (rows created per employee per project) 2. Be careful with aggregations (use COUNT(DISTINCT ...)) 3. Pagination becomes complex

M:N Grouped by Employee

Subquery Join

Join subqueries as if they were tables.

Department Statistics Join

Latest Login Join

Join + WHERE Conditions

Pre-join Filtering

Post-join Aggregation

Practical Examples

User Profile Query

Project Details + Member List

Department Hierarchy Query

Type Safety

Puri’s joins are type-safe.
LEFT JOIN and types: - Columns from LEFT JOIN tables are T | null type - Columns from INNER JOIN tables are T type - TypeScript automatically enforces null checks

Performance Optimization

Index Usage

Select Only Needed Columns

Optimize JOIN Order

Next Steps

Aggregations

Analyze data with aggregate functions

Advanced Patterns

Subqueries and complex patterns

Type Safety

Type safety in joins

Basic Queries

Back to basic queries