Метод unionAll
Метод unionAll применяется к запросу Query Builder
и позволяет объединить результаты двух или более запросов
в один результирующий набор, сохраняя все строки, включая дубликаты.
В отличие от метода union, который удаляет дублирующиеся записи,
unionAll оставляет их, что может быть полезно при подсчёте
статистики или получении всех данных без фильтрации.
Метод принимает первым параметром запрос в виде экземпляра
IlluminateDatabaseQueryBuilder или замыкание,
возвращающее такой экземпляр.
Синтаксис
<?php
DB::table('table1')->unionAll($query)->get();
?>
Пример
Давайте объединим результаты двух запросов к таблице статей,
при этом первый запрос выбирает статьи с id от 1 до 3,
а второй - статьи с id от 2 до 4:
<?php
namespace AppHttpControllers;
use IlluminateSupportFacadesDB;
class ArticleController extends Controller
{
public function index()
{
$query1 = DB::table('articles')
->select('id', 'title')
->whereBetween('id', [1, 3]);
$query2 = DB::table('articles')
->select('id', 'title')
->whereBetween('id', [2, 4]);
$res = $query1->unionAll($query2)->get();
foreach ($res as $row) {
echo $row->id . ' ' . $row->title . "\n";
}
}
}
?>
Результат выполнения кода:
["1 article 1", "2 article 2", "3 article 3", "2 article 2", "3 article 3", "4 article 4"]
Как видите, записи с id 2 и 3 дублируются,
так как присутствуют в обоих запросах.
Пример
Давайте объединим три запроса с использованием замыкания для второго и третьего запроса:
<?php
namespace AppHttpControllers;
use IlluminateSupportFacadesDB;
class ArticleController extends Controller
{
public function index()
{
$query1 = DB::table('articles')
->select('id', 'title')
->where('status', 'published');
$res = $query1
->unionAll(function ($query) {
$query->select('id', 'title')
->from('articles')
->where('status', 'draft');
})
->unionAll(function ($query) {
$query->select('id', 'title')
->from('articles')
->where('status', 'archived');
})
->get();
foreach ($res as $row) {
echo $row->title . "\n";
}
}
}
?>
Результат выполнения кода:
["article 1", "article 3", "article 5", "article 2", "article 4", "article 6"]
Здесь мы получили все статьи из трёх различных статусов, при этом порядок записей сохраняется в том порядке, в котором они были объединены.
Пример
Рассмотрим использование unionAll с сортировкой и лимитами:
<?php
namespace AppHttpControllers;
use IlluminateSupportFacadesDB;
class ArticleController extends Controller
{
public function index()
{
$query1 = DB::table('articles')
->select('id', 'title', 'views')
->where('views', '>', 100)
->limit(2);
$query2 = DB::table('articles')
->select('id', 'title', 'views')
->where('views', '<', 50)
->limit(2);
$res = $query1
->unionAll($query2)
->orderBy('views', 'desc')
->get();
foreach ($res as $row) {
echo $row->id . ' ' . $row->title . ' ' . $row->views . "\n";
}
}
}
?>
Результат выполнения кода:
["1 article 1 250", "3 article 3 180", "5 article 5 30", "6 article 6 20"]
Обратите внимание, что сортировка и лимиты применяются ко всему объединённому результату, а не к отдельным запросам.
Пример
Используем unionAll для подсчёта общего количества
записей из разных таблиц:
<?php
namespace AppHttpControllers;
use IlluminateSupportFacadesDB;
class ArticleController extends Controller
{
public function index()
{
$query1 = DB::table('articles')
->select(DB::raw("'articles' as source, id, title"))
->where('is_published', true);
$query2 = DB::table('pages')
->select(DB::raw("'pages' as source, id, title"))
->where('is_published', true);
$res = $query1
->unionAll($query2)
->get();
echo 'Total records: ' . $res->count() . "\n";
foreach ($res as $row) {
echo $row->source . ': ' . $row->title . "\n";
}
}
}
?>
Результат выполнения кода:
["Total records: 5", "articles: article 1", "articles: article 3", "pages: page 1", "pages: page 2", "pages: page 3"]