[perl][cdbi] Class::DBI::Plugin::CountGroup
ある項目で GROUP BY してそれぞれの数を集計したリストが欲しい、っていうケースってフツーによくありますよね?
↓こんなふうにしたい
SELECT artist, COUNT(*) as count FROM cd GROUP BY artist ORDER BY count DESC
そんな時、今までは普通に set_sql でベタに SQL を書いたりしてたのですが、
「これくらいのこと、何か簡単に書けるプラグインがあるはずだ」
と思って探してみたものの、見当たらないようだったので、ちょろっと書いてみました。
package Class::DBI::Plugin::CountGroup; use strict; use warnings; use SQL::Abstract; sub import { my $self = shift; my $pkg = caller(0); $pkg->columns( TEMP => 'count' ); $pkg->set_sql( count_search_where => q{ SELECT %s, COUNT(*) as count FROM __TABLE__ %s GROUP BY %s ORDER BY count DESC } ); no strict 'refs'; *{"$pkg?::count_group"} = sub { my $class = shift; my $group = (ref $_[0]) ? join ',', @{$_[0]} : $_[0]; my $where = (ref $_[1]) ? $_[1] : undef; my ($phrase, @bind) = SQL::Abstract->new->where($where); my $sth = $class->sql_count_search_where( $group, $phrase, $group ); return $class->sth_to_objects($sth, ?@bind); }; } 1;
で、こんな感じですね。
my $iterator = Music::CD->count_group('artist');
さらに、複数カラムでの GROUP BY とか、条件付きでの検索もできます。
検索条件の指定は SQL::Abstract の形式でこんな感じ。
my $iterator = Music::CD->count_group([ 'country', 'artist' ], { genre => 'ROCK', released => { -between => [ 1990, 1995 ] }, });
結構いけてると思うんですが。どーでしょう。