Cree un hash de listas, como para "todas las etiquetas para id" con perl dbi

Cree un hash de listas, como para "todas las etiquetas para id" con perl dbi

Busqué en los dbidocumentos y busqué en Google, pero no pude encontrar si había una forma nativa (dbi) de crear un hash de listas. Lo más parecido que se me ocurre es fetchall_hashrefque eso sobrescribe los resultados y solo me da el último par. Para aclarar, mi tabla es una lista de pares de algo como "id, etiqueta". Deseo agrupar todas las filas por identificación y devolver un hash donde la clave es la identificación y el "valor" es (referencia a) la lista de todas sus etiquetas. Entonces en el caso de:

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

Quiero tener:

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

es posible? Si no es así, ¿cuál es la mejor forma (la más eficiente) de hacer esto de forma no nativa? El enfoque obvio sería simplemente hacer un combo fetchall_* + push(), pero ¿hay una mejor manera?

Respuesta1

Aquí está mi enfoque actual:

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

En caso de que sea útil para alguien, mientras esperamos para ver si hay una mejor manera de hacerlo.


Editar:

Encontré otro enfoque, que consiste en utilizar GROUP_CONCATen MySQL las "etiquetas", unidas con un carácter único, que luego aparece split()en Perl. La consulta sería algo como:

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

Luego en Perl:

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

Código no probado, por lo que se aplican advertencias estándar.

La única ventaja que veo es que esto devuelve menos filas de la base de datos, por lo que tienes menos iteraciones de foreach. Tal vez alguien pueda perfilar este código y hacernos saber si hay diferencias de velocidad significativas en los enfoques.

información relacionada