문제

I want to select the MIN() and MAX() of a column from a table. But instead of querying the database twice I'd like to solve this in just one query.

I know I could do this

my $col = $schema->result_source("Birthday")->get_column("birthdate");
my $min = $col->min();
my $max = $col->max();

But it would query the database twice.

The only other solution I found is quite ugly, by messing around with the select and as attributes to search(). For example

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

Which produces this - my wanted SQL

SELECT MIN(birthdate), MAX(birthdate) FROM birthdays;

Is there any more elegant way to get this done with DBIx::Class?

And to make it even cooler, is there a way to respect the inflation/deflation of the column?

도움이 되었습니까?

해결책

You can use columns as a shortcut to combine select and as attributes as such:

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

Or, if you prefer more control over the SQL, use string refs, which can help with more complex calculations:

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

Now, if you really want to clean it up a bit, I highly recommend DBIx::Class::Helpers, which allows you to write it as such:

my $minmax = $rs->columns([
    {minBirthdate=>\"MIN(birthdate)"},
    {maxBirthdate=>\"MAX(birthdate)"},
])->hri->single;
say "$minmax->{minBirthdate} - $minmax->{maxBirthdate}";
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top