简体   繁体   中英

Laravel Union Query using Eloquent

I need to execute the following query using Eloquent but without using the DB::table function.

SELECT a.name, a.type 
FROM (
(
    SELECT name, 'Customer' as `type`
    FROM customers
)
UNION ALL 
(
    SELECT name, 'Supplier' as `type`
    FROM suppliers
)) AS a 
ORDER BY a.type ASC 
LIMIT 20

So far I was able to merge both results but I'm not able to order by the alias a nor limit the results. That being said, this works:

$a = Customers::select('name', DB::raw("'Customer' AS `type`"))->get();
$b = Suppliers::select('name', DB::raw("'Supplier' AS `type`"))->get();

$result = $a->merge($b);

But this does not $result = $a->merge($b)->limit(10);

I also tried to use the fromSub function as follows:

$result = Customers::selectRaw('a.name, a.type')->fromSub(function ($subquery) use ($a, $b) 
{
    $subquery->union($a)->union($b);
})->get();

And returns the error:

Method Illuminate\\Database\\Eloquent\\Collection::getBindings does not exist.

I also tried to construct the query inside the function and almost works, a missing ( is all that separates me from my goal.

$result = Customers::selectRaw('a.name, a.type')->fromSub(function ($subquery) 
{
    $sql = "name, 'Customer' AS type FROM customers) ";
    $sql .= ' UNION ALL ';
    $sql .= "(SELECT name, 'Supplier' AS type FROM suppliers) ";

    $subquery->select(DB::raw($sql));
}, 'a')->get();

This returns the SQL query:

SELECT a.name, a.type FROM (SELECT name, 'Customer' AS type FROM customers) UNION ALL (SELECT name, 'Supplier' AS type FROM suppliers)) as `a`

But unfortunately it is missing an ( after a.type FROM ( , it should be a.type FROM (( and I can't figure out how I add that extra ´(`.

For eloquent builder

in your case , you don't need to use subtable, just use union without subtable :

$a = Customers::select('name', DB::raw("'Customer' AS `type`"));
$b = Suppliers::select('name', DB::raw("'Supplier' AS `type`"));

$a->union($b)->orderBy('type')->limit(20);

And if you want to use with subtable , you can do it like this:

$a = Customers::select('name', DB::raw("'Customer' AS `type`"));
$b = Suppliers::select('name', DB::raw("'Supplier' AS `type`"));
$c = $a->union($b);
Customers::selectRaw('a.name, a.type')
         ->from(DB::raw("(".$c->toSql().") AS a"))
         ->mergeBindings($c->getQuery()) // if you have parameters
         ->orderBy('type')
         ->limit(20);

For query builder

you can do it like this:

$a = Customers::select('name', DB::raw("'Customer' AS `type`"));
$b = Suppliers::select('name', DB::raw("'Supplier' AS `type`"));
$c = $a->union($b);

DB::table(DB::raw("({$c->toSql()}) AS a"))
->mergeBindings($c->getQuery())
->orderBy('a.type')
->select('a.name', 'a.type')
->limit(20);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM