Load only parents with matching children
Retrieve related records
Drizzle ORM · Module
innerJoin combines rows from two Drizzle tables when a supplied SQL condition matches. It produces SQL INNER JOIN semantics and type-inferred, nested results keyed by the participating tables.
Call innerJoin on a select query with the table to join and an equality or other SQL condition. Drizzle emits an SQL INNER JOIN, returning rows only when the condition matches; the result is grouped under the participating table names and is inferred with TypeScript types.
db.select().from(table).innerJoin(joinedTable, on)| Name | Type | Description |
|---|---|---|
table | Table or selectable | The table or selectable source to join to the current query. |
on | SQL condition | The SQL expression that determines which rows match. |
A promise resolving to an array of objects containing the matching rows from the joined tables, with inferred TypeScript types.
import { eq } from 'drizzle-orm';
import { users, pets } from './schema';
const result = await db
.select()
.from(users)
.innerJoin(pets, eq(users.id, pets.ownerId));This query returns users only when their IDs match a pet's ownerId, and includes both table-shaped results.
Retrieve related records
Combine normalized data
Use typed SQL joins
innerJoin combines two tables using a supplied SQL condition, such as eq(users.id, pets.ownerId). Because it is an SQL INNER JOIN, only matching rows are returned, and Drizzle infers a result object containing both table fields.
Follow-up: How would you preserve users without pets? Use leftJoin instead, accepting that the joined table's result can be null.
The first argument after from is the table being joined, and the second is the join condition. A typical call is db.select().from(users).innerJoin(pets, eq(users.id, pets.ownerId)).
Follow-up: How can the selected shape be narrowed? Pass an object to select, such as select({ user: users, pet: pets }), rather than selecting every column.
Drizzle translates the method call into SQL resembling select ... from users inner join pets on users.id = pets.owner_id. The returned rows are represented as nested objects keyed by the participating tables.
Follow-up: What is the lateral counterpart? Build and alias a subquery, then call innerJoinLateral(subquery, sqltrue).
innerJoinLateralleftJoinrightJoinfullJoincrossJoineq