Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

RomainB's avatar
Level 13

Use InnerJoin with a "complex" SQL Request

Hi all.

My goal is to retrieve nearest Providers model, located by longitude/latitude field contained in Towns table.

My tables are like:

Providers

`id` | `name` | `address_street` | `address_postal_code` | `address_town`

Towns ( where location is point field)

`id` | `name` | `postal_code` | `location`

The raw sql query is this:

SELECT `name`, `address_street`, `address_postal_code`, `address_town`
FROM (
    SELECT `postal_code`
    FROM `towns`
    ORDER BY ST_DISTANCE(`towns`.`location`, (
        SELECT `towns`.`location`
        FROM `towns`
        WHERE `towns`.`postal_code`= '83500'
        LIMIT 1)
    ) ASC
    LIMIT 5
) AS `nearby`
INNER JOIN `providers` ON `providers`.`address_postal_code` = `nearby`.`postal_code`
LIMIT 5

This query is working perfectly when submitted directly in database.

First I tried to use directly my raw query:

DB::query(DB::raw('
    SELECT `name`, `address_street`, `address_postal_code`, `address_town`
    FROM (
        SELECT `postal_code`
        FROM `towns`
        ORDER BY ST_DISTANCE(`towns`.`location`, (
            SELECT `towns`.`location`
            FROM `towns`
            WHERE `towns`.`postal_code`= '.$postal_code'
            LIMIT 1)
        ) ASC
        LIMIT 5
    ) AS `nearby`
    INNER JOIN `providers` ON `providers`.`address_postal_code` = `nearby`.`postal_code`
    LIMIT 5
'))->get();

But SELECT FROM SELECT seems to not work with DB::raw: SQLSTATE[HY000]: General error: 1096 No tables used (SQL: select *)

Also it's not really eye-friendly in my Laravel app. So I want to use Laravel builder facade. But Hmm... That's not so easy...

I tried some few things, but I'm not able to get the same query, especially the inner join:

$visitor_town_query = Town::query();
$visitor_town = $visitor_town_query
         ->select(['location'])
         ->where('postal_code', $postal_code)
         ->take(1); // Some nearby-towns may have the same postal code

$five_nearest_towns_query = Town::query();
$five_nearest_towns = $five_nearest_towns_query
                      ->select(['postal_code'])
                      ->orderBY(DB::raw("ST_DISTANCE(`location`, (".$visitor_town->toSql()."))"), 'asc')
                      ->take(5);

$five_nearest_providers_query = DB::query()
                                ->select(['name', 'phone', 'address_town', 'address_street', 'address_postal_code'])
                                ->fromRaw('('.$five_nearest_towns->toSql().')')
                                ->take(5);


return $five_nearest_providers_query->toSql();

I'm using toSql() function on $five_nearest_towns just to see what I need to add in my query. Here is the SQL request generated:

select `name`, `phone`, `address_town`, `address_street`, `address_postal_code` from (select `postal_code` from `towns` order by ST_DISTANCE(`location`, (select `location` from `towns` where `postal_code` = ? limit 1)) asc limit 5) limit 5

Where to place inner join?? I feel like I ran in a dead end and maybe I choose wrong way?

0 likes
3 replies
Tray2's avatar

Try using

DB::select('<your query here>');
RomainB's avatar
RomainB
OP
Best Answer
Level 13

Woaw... It was that simple...

It's still remain eye-unfriendly so if someone knows where to put my inner join...

[EDIT] I finally found solution, this is my final builder query:

$visitor_town_query = Town::query();
$visitor_town = $visitor_town_query
->select(['location'])
->where('postal_code', $postal_code)
->take(1);

$five_nearest_towns_query = Town::query();
$five_nearest_towns = $five_nearest_towns_query
->select(['postal_code'])
->orderBY(DB::raw("ST_DISTANCE(`location`, (".$visitor_town->toSql()."))"), 'asc')
->offset(10)
->limit(5);

$five_nearest_providers_query = DB::query()
->select(['name', 'phone', 'address_town', 'address_street', 'address_postal_code'])
->fromSub($five_nearest_towns, 'nearby')
->join('providers', 'providers.address_postal_code', '=', 'nearby.postal_code')
->distinct();
1 like
Milla's avatar

Thank you so very much for this answer - now I got a clue how to write my SQL queries in an elegant Eloquent style..

Please or to participate in this conversation.