Busqué en los dbi
documentos 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_hashref
que 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_CONCAT
en 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.