How to create a subquery using Laravel Eloquent?

Stefan Izdrail

Founder & Senior Architect · 2026-06-29

Laravel Company
Creating Subqueries Using Laravel Eloquent In this article, we will look at how to create subqueries using Laravel Eloquent. It'll allow you to combine multiple queries into one and avoid making multiple database calls, thus improving performance. We will cover the basics of working with subqueries, using examples. Let us begin by understanding a simple but effective way of writing subqueries in Laravel Eloquent: 1. Define your main query (the outer query) and perform any necessary operations like sorting or filtering. In this case, it's retrieving the list of prices ordered by price_date for specific tickers.
$start_date = //some date;

   $prices = BenchmarkPrice::select('price_date', 'price')
     ->orderBy('price_date', 'ASC')
     ->where('ticker', $this->ticker)
     ->get();
2. Create a subquery that performs other specific tasks, like finding the earliest date on or after your given start_date, for example. This can be extracted as a separate method and later called in the main query to use its output.
public function getEarliestDateOnOrAfter() {
     return BenchmarkPrice::select(DB::raw('min(price_date) as min_date'))
       ->where('price_date', '>=', $this->start_date)
       ->where('ticker', $this->ticker)
       ->pluck('min_date');
   }
3. Merge the results of both queries into a single query by using the `get()` method call to execute them and return their result sets combined:
$prices = BenchmarkPrice::select('price_date', 'price')
     ->orderBy('price_date', 'ASC')
     ->where('ticker', $this->ticker)
     ->get();

   $start_date = //some date;
   $earliestDateOnOrAfter = $this->getEarliestDateOnOrAfter();

   $prices = BenchmarkPrice::select('price_date', 'price')
     ->orderBy('price_date', 'ASC')
     ->where('ticker', $this->ticker)
     ->where(function($q) use ($start_date, $earliestDateOnOrAfter) {
       $q->orWhere('price_date', $this->getEarliestDateOnOrAfter());
     })
     ->get();
If you prefer a more compact solution without defining an intermediate method, you can write the code as follows: ```php $prices = BenchmarkPrice::select('price_date', 'price') ->orderBy('price_date', 'ASC') ->where('ticker', $this->ticker) ->get(); $start_date = //some date; $earliestDateOnOrAfter = DB::table('benchmark_prices')->selectRaw('min(price_date) as min_date') ->where('price_date', '>=', $this->start_date) ->where('ticker', $this->ticker) ->pluck('min_date'); $prices = BenchmarkPrice::select('price_date', 'price') ->orderBy('price_date', 'ASC') ->where('ticker', $this->ticker) ->where(function($q) use ($start_date, $earliestDateOnOrAfter) { $q->orWhere('price_date', $earliestDateOnOrAfter); }) ->get(); ``` In this case, the subquery is embedded in the main query via a closure passed to `where()`. Although it's shorter and more efficient than explicitly creating an intermediate method, this approach isn't as readable. As always, pick the most suitable solution based on your application requirements. Note that when using `orWhere` blocks inside your subquery, you may encounter issues with quoting. This is because Laravel Eloquent automatically quotes column and table names in `where()` and `orWhere()`. However, these are not quoted within the closure passed to `where()`, leading to incorrectly unquoted columns in your query. To solve this issue, you can move your `orWhere` blocks outside of the closure: ```php $prices = BenchmarkPrice::select('price_date', 'price') ->orderBy('price_date', 'ASC') ->where('ticker', $this->ticker) ->get(); $start_date = //some date; $earliestDateOnOrAfter = DB::table('benchmark_prices')->selectRaw('min(price_date) as min_date') ->where('price_date', '>=', $this->start_date) ->where('ticker', $this->ticker) ->pluck('min_date'); $prices = BenchmarkPrice::select('price_date', 'price') ->orderBy('price_date', 'ASC') ->where('ticker', $this->ticker) ->where(function($q) use ($start_date, $earliestDateOnOrAfter) { if ($start_date) $q->orWhere('price_date', $start_date); $d = DB::table('benchmark_prices')->selectRaw('min(price_date)') ->where('price_date', '>=', $this->start_date) ->where('ticker', $this->ticker); if ($start_date) $q->orWhere('price_date', $d); }) ->get(); ``` By using subqueries, you can create more complex queries and reduce the total number of database calls. This results in better performance when handling large datasets or complex logic, making your Laravel application more efficient.