Reputation: 1444
I need a way to sort my models by two columns (but not as order by x, y does). I have a priority
column that can 'boost' a model in results, and standard created_at
that should be sorting key when priority
is not set. The only way I have found to do this was with unions.
With query like this:
(SELECT * FROM `charts` WHERE priority IS NOT NULL ORDER BY priority ASC)
UNION (SELECT * FROM `charts` WHERE priority IS NULL AND created_at IS NOT NULL ORDER BY CREATED_AT ASC)
UNION (SELECT * FROM `charts` WHERE created_at IS NULL)
So I tried to do something like:
public function scopeSortPriority($query)
{
return $query->whereNotNull('priority')
->orderBy('priority')
->union($query->whereNull('priority')
->whereNotNull('created_at')
->orderBy('created_at'))
->union($query->whereNull('priority')
->whereNull('created_at'));
}
But it sadly does not work.
Is there an other way to accomplish what I want in SQL? Otherwise - how should I rebuild this scope to make it work?
Upvotes: 3
Views: 1250
Reputation: 2147
The problem is that you are using $query
in your unions.
If you know that the common part of your query and your unions allways will be \DB::table('charts')
you can do:
$query->whereNotNull('priority')
->orderBy('priority')
->union(\DB::table('charts')->whereNull('priority')
->whereNotNull('created_at')
->orderBy('created_at'))
->union(\DB::table('charts')->whereNull('priority')
->whereNull('created_at'));
If $query
will be the same but can change you can do:
$query2 = clone $query;
$query3 = clone $query;
$query->whereNotNull('priority')
->orderBy('priority')
->union($query2->whereNull('priority')
->whereNotNull('created_at')
->orderBy('created_at'))
->union($query3->whereNull('priority')
->whereNull('created_at'));
In both case the output of the sql is:
(select * from `charts` where `priority` is not null order by `priority` asc) union (select * from `charts` where `priority` is null and `created_at` is not null order by `created_at` asc) union (select * from `charts` where `priority` is null and `created_at` is null)
Upvotes: 5