Построить хэш списков, как для «всех тегов для id» с помощью perl dbi

Построить хэш списков, как для «всех тегов для id» с помощью perl dbi

Я поискал в dbiдокументации и в гугле, но не смог найти, есть ли собственный (dbi) способ создания хеша списков. Самый близкий, который я могу придумать, это , fetchall_hashrefно он перезаписывает результаты, давая мне только то, что было последней парой. Для ясности, моя таблица представляет собой список пар чего-то вроде "id, tag". Я хочу сгруппировать все строки по id и вернуть хеш, где ключом является id, а "value" - это (ссылка на) список всех его тегов. Так что в случае:

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. Может быть, кто-то сможет профилировать этот код и сообщить нам, есть ли существенные различия в скорости в подходах.

Связанный контент