[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 ] },
                                       });

結構いけてると思うんですが。どーでしょう。