KifayatMsd's avatar

select statement inside another select

Greetings .... How to write the following query in laravel eloquent ORM.

select c.*, (SELECT COUNT(t.id) FROM dental_support_tickets t WHERE t.category_id=c.id AND t.status=0) AS num_tickets, (SELECT COUNT(a.id) FROM dental_support_category_admin a WHERE a.category_id=c.id) AS num_admins FROM dental_support_categories c WHERE c.status=0 order by c.title ASC

They above query if used as it is inside DB::select(), then I am unable to use pagination on it e.g. $records->render() in my view.

0 likes
6 replies
JarekTkaczyk's avatar

@KifayatMsd Check this package https://github.com/jarektkaczyk/eloquence - it provides Subquery helper class for such cases. Then you need something like this:

// assuming you have an eloquent model Ticket, for presentation
$countTickets = new \Sofa\Eloquence\Subquery(
    Ticket::from('dental_support_tickets as t')
        ->selectRaw('count(t.id)')->whereRaw('t.category_id=c.id')->where('t.status', '0'),
    'num_tickets' // alias
);

// now let's use query builder
$countAdmins = new \Sofa\Eloquence\Subquery(
    DB::table('dental_support_category_admin as a')
        ->selectRaw('count(a.id)')->whereRaw('a.category_id=c.id'), 
    'num_admins' // alias
);

// finally eloquent result
Category::from('dental_support_categories as c')
        ->select('c.*', $countTickets, $countAdmins)
        ->addBinding($countTickets->getBindings(), 'select')
        ->where('c.status', 0)
        ->orderBy('c.title', 'asc')
        ->paginate()

It will automatically build the query for you:

select 
    c.*, 
    (select count (t.id) from dental_support_tickets t where t.category_id=c.id and t.status = ?) as num_tickets,
    (select count(a.id) from dental_support_category_admin a where a.category_id=c.id) as num_admins 
from dental_support_categories c 
where c.status = ? 
order by c.title ASC
2 likes
KifayatMsd's avatar

@phildawson I tried it using \DB::raw() but still no joy.

$categories = \DB::table('dental_support_categories as c') ->select(\DB::raw('(COUNT(t.id) FROM dental_support_tickets t WHERE t.category_id=c.id AND t.status=0) AS num_tickets')) ->where('c.status', 0) ->orderBy('c.title','ASC') ->get();

phildawson's avatar
Level 26

@KifayatMsd How about?

$categories = \DB::table('dental_support_categories AS c')
    ->select(\DB::raw('c.*, (SELECT COUNT(t.id) FROM dental_support_tickets t WHERE t.category_id=c.id AND t.status=0) AS num_tickets, (SELECT COUNT(a.id) FROM dental_support_category_admin a WHERE a.category_id=c.id) AS num_admins'))
    ->where('c.status', 0)
    ->orderBy('c.title')
    ->get();
4 likes
critic's avatar

The worst thing is that you have to think how it works, but not as it should be. Please replace Eloquence to someone more reliable.

Please or to participate in this conversation.