如何在DBIx :: Class中使用交叉表函数

时间:2014-04-18 15:44:29

标签: sql postgresql catalyst dbix-class

我正在尝试在Catalyst应用程序中使用DBIx :: Class来创建一个将在交叉表列表中生成结果的SQL语句。这是我试图生成的SQL的一个例子。

select * from crosstab('
    select event_member_id, round, gross from results where event_id = 21 and round = 6 or round = 7 order by 1, 2')
    AS results(player integer, Saturday integer, Sunday integer)
;

我试图创建一个名为cross_tab的自定义方法,如下所示:

    sub cross_tab {
    my $self = shift;
    my $attributes = shift || {};

    $attributes->{'select'} = "* from crosstab('
        select event_member_id, round, gross from results where
        event_id = 21 and
        round = 6 or round = 7
        order by 1, 2')"
    ;`enter code here`

    $attributes->{'as'} = [
        'results(player integer, Saturday integer, Sunday integer)',
    ];

    return $self->search({}, $attributes);

}

这会创建如下所示的SQL:

SELECT me.* from crosstab('
    select event_member_id, round, gross from results where 
    event_id = 21 and 
    round = 6 or round = 7 
    order by 1, 2') 
FROM results me;

这是相当接近的,但我不想要" me"在开头附加,我也不想添加添加FROM语句" FROM结果我"。我认为这是通过搜索方法添加的。

除了"搜索"还有更好的DBIx :: Class方法吗?或者有没有办法告诉DBIx :: Class不要添加附加子句?

1 个答案:

答案 0 :(得分:0)

我不确定你为什么不想要'我'在那里。 DBIC总是添加它,并且它不会妨碍在处理结果集中的数据时过滤掉它。

最简单的方法是获得你想做的事可能是创建一个virtual view。然后,您可以在该视图中定义确切的查询,并直接在结果源上选择,就像它是模式中的任何其他表一样。

您也可以使用反向引用的字符串语法(\'sql literal')通过子查询和一些自定义SQL实现类似的结果,尽管总而言之它会更难。

这样的事情应该做:

package MyApp::Schema::Result::VirtualCrosstab;

use base qw/DBIx::Class::Core/;

__PACKAGE__->table_class('DBIx::Class::ResultSource::View');

__PACKAGE__->table('virtual_crosstab');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition(qq[
    select * from crosstab(
        select event_member_id, round, gross
        from results
        where event_id = 21 and round = 6 or round = 7 order by 1, 2
    )
    AS results(player integer, Saturday integer, Sunday integer)
;
]);
__PACKAGE__->add_columns(
  'player' => {
    data_type => 'integer',
    is_auto_increment => 1,
  },
  'saturday' => {
    data_type => 'integer',
  },
  'sunday' => {
    data_type => 'integer',
  },
);

1;