Laravel Eloquent: How to select from multiple tables
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Laravel Eloquent: How to Select from Multiple Tables Efficiently
As developers working with relational data in Laravel, navigating complex relationships between modelsâselecting data across multiple tablesâis a daily task. While Eloquent makes defining these relationships incredibly intuitive, pulling related data efficiently often requires understanding how the underlying query builder works.
This post addresses a common challenge: how to fetch nested data, such as finding all occupants of a house and simultaneously retrieving the associated job details for each occupant. We will explore the most efficient methods using Laravel Eloquent, ensuring your database queries are fast and readable.
## The Scenario: Navigating Nested Relationships
Letâs assume we have three models: `House`, `Occupant`, and `Job`. The relationships are set up as follows:
1. A `House` has many `Occupants` (One-to-Many).
2. An `Occupant` has one `Job` (One-to-One or Many-to-One).
The goal is to start with a specific `House` and retrieve its occupants, along with the job title for each occupant, in a single, efficient query operation.
## The Pitfall of Simple Chaining
You correctly identified that simple chaining often looks appealing:
```php
$house = House::find($house_id);
// Attempted approach
$occupants_and_jobs = $house->occupants()->where('active', 1)->job()->get();
```
While this syntax seems logical, relying on implicit relationship chaining like `->job()` directly within a query scope can sometimes lead to complex and less optimized SQL queries, especially when dealing with deeper nesting or filtering. Furthermore, if you are querying across models rather than through a specific parent model, Eloquent's focus shifts to managing the relationship definitions correctly.
## The Efficient Solution: Eager Loading (`with()`)
The most performant and idiomatic way to solve this problem in Laravel is by using **Eager Loading**. Eager loading tells Eloquent to retrieve all necessary related models in advance, typically executing just two or three efficient `JOIN` queries instead of performing N+1 queries (where N is the number of records).
To load data across multiple levels, you chain the `with()` method. You must specify the relationships you want loaded from the starting model.
### Step-by-Step Implementation
To get the occupants and their respective jobs for a specific house, we apply eager loading:
```php
$house = House::with('occupants.job')
->where('id', $house_id)
->first();
if ($house) {
echo "House Name: " . $house->name . "\n";
foreach ($house->occupants as $occupant) {
// Accessing the job data is now direct, no extra query needed!
echo "Occupant: " . $occupant->name . ", Job: " . $occupant->job->title . "\n";
}
}
```
### Explanation of the Code
1. **`House::with('occupants.job')`**: This is the core of the solution. We instruct Eloquent to load the `occupants` relationship *and* for each occupant, load their related `job`. The dot notation (`.`) clearly defines the nested relationship path.
2. **`->where('id', $house_id)->first()`**: We scope this query to find the specific house we are interested in.
3. **Accessing the Data**: Once the data is eager-loaded, accessing related data (like `$occupant->job`) becomes instantaneous because Eloquent has already fetched the necessary `Job` records alongside the `Occupant` records.
This approach ensures that you avoid performance bottlenecks associated with lazy loading and results in cleaner database interaction. For deep or complex relations, understanding these eager loading techniques is fundamental to mastering **Laravel** development principles found on platforms like [https://laravelcompany.com](https://laravelcompany.com).
## Conclusion
Selecting data across multiple related tables in Laravel Eloquent is best achieved not by manually chaining relationship methods within a single query structure, but by leveraging the power of Eager Loading using the `with()` method. By properly eager loading nested relationships (e.g., `with('relationship_name.nested_relationship')`), you delegate the complex joining and data retrieval to Eloquent, resulting in highly efficient, readable, and scalable code. Always prioritize eager loading when dealing with related data sets to maintain optimal performance.