代码之家  ›  专栏  ›  技术社区  ›  porton

如何在带有dbix::类的select部分中使用子查询?

  •  2
  • porton  · 技术社区  · 7 年前

    请帮助在中编写此mysql查询 DBIx::Class (有一个关于如何在中使用子查询的示例 dbix::类 ):

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

    (我知道它可以重写为 JOIN GROUP BY ,但我想要的是子查询(举个例子)。

    dbix::类 文档对在 WHERE 但是我没有找到如何在 SELECT 字段列表(如上例所示)。

    2 回复  |  直到 7 年前
        1
  •  4
  •   simbabque    7 年前

    你在正确的轨道上。这个 as_query 就是你需要的。但你也需要 columns option 在第二个hashref中。确保你使用 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
    
        2
  •  0
  •   Eugen Konkov    7 年前

    万一 prefetch 如果要选择子查询结果,则必须命名子查询,否则将出现错误(请参见simbabque下的注释 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 /],
    });
    
    推荐文章