... $sth->execute; my (%rows,%cols,$rtime,$dev,$value); while (($rtime,$dev,$value)=$sth->fetchrow) { $rows{$rtime}{$dev}=$value; $cols{$dev}++; } $sth->finish if $sth->{Active}; # really don't need finish if you got all the data # now column headers can be computed my @cols=sort keys %cols; map { $cols{$cols[$_]}=$_+1 } 0..$#cols; # get indexes my @headers=('RTIME',sort keys %cols); my @row; print join("\t",@headers),"\n"; # and rows can be extracted (empty cells where a dev wasn't seen for a particular rtime) for $rtime (sort keys %rows) { $row[0]=$rtime; map { $row[$cols{$_}]=$rows{$rtime}{$_} } keys %{$rows{$rtime}}; print join("\t",@row),"\n"; }