-->

Subqueries in DBIx::Class

2019-07-15 12:39发布

问题:

I have spent too much time on this, and still cannot get the syntax to work. Is this select statement possible in DBIx::Class?

"SELECT A.id, A.name, count(C.a_id) AS count1, 
   (SELECT count(B.id FROM A, B WHERE A.id=B.a_id GROUP BY B.a_id, A.id) AS count2
 FROM A LEFT OUTER JOIN C on A.id=C.a_id GROUP BY C.a_id, A.id"

This code below works in DBIx::Class to pull the count for table 'C', but multiple efforts of mine to add in the count for table 'B' have repeatedly failed:

     my $data= $c->model('DB::Model')
                    ->search({},
                            {
                                    join => 'C',
                                    join_type => 'LEFT_OUTER',
                                    distinct => 1,
                                    'select' => [ 'me.id','name',{ count => 'C.id', -as => 'count1'} ],
                                    'as' => [qw/id name count1 /],
                                    group_by => ['C.a_id','me.id'],
                            }
                    )
                    ->all();

I am trying to get two counts in one query so that the results are saved in one data structure. On another forum it was suggested that I make two separate search calls and then union the results. When I looked at the DBIx::Class documentation though, it mentioned that 'union' is being deprecated. Using the 'literal' DBIx::Class doesn't work because it's only meant to be used as a where clause. I do not want to use a view (another's suggestion) because the SQL will eventually be expanded to match upon one of the id's. How do I format this query to work in DBIx::Class? Thank you.

回答1:

DBIx::Class supports subqueries pretty conveniently by using the as_query method on your subquery resultset. There are some examples in the cookbook. For your use case, it'd look something like:

# your subquery goes in its own resultset object
my $subq_rs = $schema->resultset('A')->search(undef, {
  join => 'B',
  group_by => [qw/A.id B.id/],
})->count_rs;

# the subquery is attached to the parent query with ->as_query
my $combo_rs = $schema->resultset('A')->search(undef, {
    select => [qw/ me.id me.name /,{ count => 'C.id' }, $subq_rs->as_query],
    as => [qw/ id name c_count b_count/],
});