Соединение таблиц Inner Join (внутреннее соединение)
Для выполнения объединения INNER JOIN
предназначен метод join()
конструктора запросов. Первый аргумент метода join()
— имя таблицы, которую необходимо присоединить, а остальные аргументы указывают условия для присоединения.
Таблица profiles
содержит профили пользователя — те данные, которые необходимы для оформления заказа в магазине (телефон и адрес доставки). Мы получаем все заказы пользователя, объединяя таблицы users
, orders
и profiles
. Из таблицы users
берем имя и адрес почты, из таблицы profiles
— номер телефона, а из таблицы orders
— сумму каждого заказа. Поскольку профилей может быть несколько, мы берем данные из основного профиля.
Первый вызов всегда идёт через table()
в котором указываем таблицу базы данных. Метод get()
указывает на окончание запроса и выполняет его в базу данных, возвращает объект Illuminate\Support\Collection
c результатами в котором каждый результат, это экземпляр класса stdClass
.
$userOrders = DB::table('users')
->join('profiles', 'users.id', '=', 'profiles.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.name', 'users.email', 'profiles.phone', 'orders.amount')
->where('users.id', '=', auth()->user()->id)
->where('profiles.default', '=', true)
->get();
SELECT
`users`.`name`, `users`.`email`, `profiles`.`phone`, `orders`.`amount`
FROM
`users`
INNER JOIN `profiles` ON `users`.`id` = `profiles`.`user_id`
INNER JOIN `orders` on `users`.`id` = `orders`.`user_id`
WHERE
`users`.`id` = 2 AND `profiles`.`default` = 1
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[name] => Сергей Иванов
[email] => ivanov.s@mail.ru
[phone] => +7 (926) 111-11-11
[amount] => 4895.00
)
[1] => stdClass Object
(
[name] => Сергей Иванов
[email] => ivanov.s@mail.ru
[phone] => +7 (926) 111-11-11
[amount] => 4331.00
)
[2] => stdClass Object
(
[name] => Сергей Иванов
[email] => ivanov.s@mail.ru
[phone] => +7 (926) 111-11-11
[amount] => 10200.00
)
)
)
Чтобы создать более сложные условия объединения таблиц, нужно передать вторым аргументом метода join()
функцию-замыкание:
$userOrders = DB::table('users')
->join('profiles', function ($join) {
$join->on('users.id', '=', 'profiles.user_id')
->where('users.id', '=', auth()->user()->id)
->where('profiles.default', '=', true);
})
->join('orders', function ($join) {
$join->on('users.id', '=', 'orders.user_id');
})
->select('users.name', 'users.email', 'profiles.phone', 'orders.amount')
->where('orders.amount', '>', 10000)
->get();
SELECT
`users`.`name`, `users`.`email`, `profiles`.`phone`, `orders`.`amount`
FROM
`users`
INNER JOIN `profiles` ON `users`.`id` = `profiles`.`user_id` AND `users`.`id` = 2 AND `profiles`.`default` = 1
INNER JOIN `orders` ON `users`.`id` = `orders`.`user_id`
WHERE
`orders`.`amount` > 10000
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[name] => Сергей Иванов
[email] => ivanov.s@mail.ru
[phone] => +7 (926) 111-11-11
[amount] => 10200.00
)
)
)
Это практически тот же запрос, только мы отбираем не все заказы пользователя, а только те, сумма которых больше 10000
рублей.