我搜索了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 的迭代次数会更少。也许有人可以分析一下这段代码,并让我们知道这些方法是否存在明显的速度差异。