在一个查询中从DBIx :: Class :: ResultSetColumn获取SQL MIN()和MAX()

gha*_*ndi 2 sql perl orm dbix-class

我想从表中选择MIN()MAX()列.但是,我只想在一次查询中解决这个问题,而不是两次查询数据库.

我知道我能做到这一点

my $col = $schema->result_source("Birthday")->get_column("birthdate");
my $min = $col->min();
my $max = $col->max();
Run Code Online (Sandbox Code Playgroud)

但它会查询数据库两次.

我发现的唯一其他解决方案是非常丑陋,通过搞乱selectas属性search().例如

my $res = $rs->search({}, {
   select => [ {min => "birthdate"}, {max => "birthdate"},
   as     => [qw/minBirthdate maxBirthdate/]
});
say $res->get_column("minBirthdate")->first() . " - " . $res->get_column("maxBirthdate")->first();
Run Code Online (Sandbox Code Playgroud)

产生这个 - 我想要的SQL

SELECT MIN(birthdate), MAX(birthdate) FROM birthdays;
Run Code Online (Sandbox Code Playgroud)

有没有更优雅的方式来完成这项工作DBIx::Class

为了使其更冷,有没有办法尊重色谱柱的膨胀/放气?

kbe*_*son 6

您可以使用作为快捷方式来组合selectas属性,如下所示:

my $res = $rs->search(undef, {
    columns => [
        { minBirthdate => { min => "birthdate" } },
        { maxBirthdate => { max => "birthdate" } },
    ]
});
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望更多地控制SQL,请使用字符串引用,这可以帮助进行更复杂的计算:

 my $res = $rs->search(undef, {
    columns => [
        { minBirthdate => \"MIN(birthdate)" },
        { maxBirthdate => \"MAX(birthdate)" },
    ]
});
Run Code Online (Sandbox Code Playgroud)

现在,如果你真的想要清理它,我强烈推荐DBIx :: Class :: Helpers,它允许你这样写:

my $minmax = $rs->columns([
    {minBirthdate=>\"MIN(birthdate)"},
    {maxBirthdate=>\"MAX(birthdate)"},
])->hri->single;
say "$minmax->{minBirthdate} - $minmax->{maxBirthdate}";
Run Code Online (Sandbox Code Playgroud)