perl dbi を使用して、「id のすべてのタグ」としてリストのハッシュを作成します。

perl dbi を使用して、「id のすべてのタグ」としてリストのハッシュを作成します。

ドキュメントを検索したりdbi、Google で検索したりしましたが、リストのハッシュを構築する (dbi) ネイティブな方法があるかどうかはわかりませんでした。私が思いつくfetchall_hashref限りでは、最も近い方法は、結果を上書きし、最後のペアだけが返されるというものです。明確に言うと、私のテーブルは、「id、tag」のようなペアのリストです。すべての行を id でグループ化し、キーが id で、「値」がすべてのタグのリスト (への参照) であるハッシュを返したいと考えています。次の場合:

id1, tag1
id1, tag2
id2, tag3
id2, tag1

私は手に入れたい:

{'id1' => ['tag1', 'tag2'],
 'id2' => ['tag3', 'tag1'] }

これは可能ですか? 不可能な場合、ネイティブ以外でこれを行う最善 (最も効率的) な方法は何ですか? 明らかなアプローチは、単に fetchall_* + push() の組み合わせを実行することですが、もっと良い方法はありますか?

答え1

私の現在のアプローチは次のとおりです。

my $ret = {};
foreach (@{ $sth->fetchall_arrayref(  ) }) { # returns ref to array
    push  @{ $ret->{ $_->[0] } }, $_->[1] ;
    }
return $ret;

これが誰かの役に立つかもしれないので、もっと良い方法があるかどうか確認するまで待ちます。


編集:

GROUP_CONCAT私は別のアプローチを見つけました。それは、 MySQL で「タグ」に使用し、一意の文字で結合し、それをsplit()Perl で使用するというものです。クエリは次のようになります。

SELECT id, GROUP_CONCAT(tag, '|')
FROM mytable
GROUP BY tag

次に、perl で次のようにします。

my $ret = {};
foreach (@{ $sth->fetchall_arrayref(  ) }) { # returns ref to array
    push  @{ $ret->{ $_->[0] } }, split("|", $_->[1]) ;
    }
return $ret;

テストされていないコードなので、標準の警告が適用されます。

私が見つけた唯一の利点は、データベースから返される行が少なくなり、foreach の反復回数が少なくなることです。誰かがこのコードをプロファイルして、アプローチに大幅な速度の違いがあるかどうかを知らせてくれるかもしれません。

関連情報