Как использовать подзапрос в части SELECT с DBIx :: Class? - PullRequest
0 голосов
/ 04 июля 2018

Помогите, пожалуйста, написать этот запрос MySQL в DBIx::Class (чтобы получить пример использования подзапросов в DBIx::Class):

SELECT x, (SELECT COUNT(*) FROM t2 WHERE t2.y=x) AS c FROM t1 WHERE t1.z=123

(я знаю, что это можно переписать как JOIN с GROUP BY, но я хочу именно подзапрос (для примера, чтобы получить в свои руки).)

DBIx::Class документы дают подробный обзор использования подзапросов в предложении WHERE, но я не нашел, как использовать подзапрос в списке полей SELECT (как в примере выше).

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

В случае prefetch, и вы хотите выбрать результат подзапроса, вы должны назвать свои подзапросы, в противном случае вы получите ошибку (см. Комментарии под answer ответа *)

my $partial =  $c->model( 'ServicePackageSet' )->search([
    { service_type_id_covered => { -ident => 'me.id' } },
    { service_type_id_surplus => { -ident => 'me.id' } },
],{ select => \1 });

my $pricelist =  $c->model( 'ServiceTree' )->search({
},{
    '+select' => { exists => $partial->as_query },
    '+as' => [ 'partial' ],
    prefetch => [qw/ Price Package /],
    order_by => [qw/ Package.short_name name /],
});

хотя, если вы хотите использовать подзапрос в качестве фильтра, он будет работать без именования:

my $pricelist =  $c->model( 'ServiceTree' )->search({
    -not_exists => $partial->as_query
},{
    prefetch => [qw/ Price Package /],
    order_by => [qw/ Package.short_name name /],
});
0 голосов
/ 05 июля 2018

Вы были на правильном пути. as_query - это то, что вам нужно. Но вам также понадобится опция columns во втором хешире. Убедитесь, что вы используете count_rs для подзапроса, который переворачивает внутренний переключатель, чтобы создать набор результатов с COUNT(*) в нем.

my $obj = ResultSet('TableOne')->search(
    { 
         z => 123,
    },
    {
        columns => [
            'x',
            {
                c => ResultSet('TableTwo')->search(
                    {
                        'y' => {
                            -ident => 'me.x',
                        },
                    },
                    {
                        alias => 'sub_query', # this name is arbitrary
                    },
                )->count_rs->as_query,
            },
        ],
    }
)->first;

Результирующий запрос будет выглядеть примерно так:

SELECT me.x, ( 
    SELECT COUNT( * ) 
      FROM table_two sub_query
    WHERE y = me.x
   )
  FROM table_one me
WHERE me.z = 123

Как видите, значение, которое мы выбрали с помощью подзапроса, не называется c в SQL, но оно называется c в данных объекта.

use DDP;
p $obj;

DB::Result::TableOne  {
    # ...
    internals: {
        _column_data     {
            x        "foo",
            c        "bar"
        },
        _in_storage      1,
        _result_source   DBIx::Class::ResultSource::Table
    }
}

Вы можете получить к нему доступ с помощью get_column для объекта строки.

say $obj->get_column('c');
# bar
...