use strict; use DBI; my $dbh; #SET THIS TO A VALID DBI CONNECTION HANDLE. my @rowheads = qw/fiscal_year sale_in_territory/; my @colheads = qw/class product_id/; my @datacols = qw/units_sold/; my $cubetable = 'transactions'; my @pivots = @rowheads; push @pivots, @colheads; my (%values,%names,%ordinals,%filtered,%totals,%columnheaders); my $sth = $dbh->prepare('select '.join(',',@rowheads).','.join(',',@colheads).','.join(',',@datacols).' from '.$cubetable.' ORDER BY '.join(',',@pivots)) || die $dbh->errstr; $sth->execute || die $dbh->errstr; my @row; while (@row = $sth->fetchrow_array) { #put the data values in a safe place my @data; for (my $i = 0; $i < @datacols; $i++) { my $d = pop @row; push @data,$d; } my $continue = 0; foreach (@data) { $continue = 1 if defined $_; } next unless $continue; my @key = @{GetKey(@row)}; my $key = join(' ',@key); if (defined $values{$key}) { my $count = -1; foreach (@{$values{$key}}) { $_ = $_ + $data[$count++]; } } else { $values{$key} = \@data; } #now set up the column header hash splice(@key,0,(@rowheads)); $key = join(' ',@key); if (defined $columnheaders{$key}) { my $count = -1; foreach(@{$columnheaders{$key}}) { $_ = $_ + $data[$count++]; } } else { $columnheaders{$key} = \@data; } } #build the column headers in a 2D array #my $colcount = 1; #foreach (@colheads) { # $colcount = $colcount * (@{$names{$_}}); #} #$colcount = $colcount * (@datacols); my $stop; my @colkey; my $count = 0; foreach (@colheads) { $colkey[$count] = 0; $stop = $stop.$#{$names{$colheads[$count]}}.' '; $count++; } chop $stop; my @cols; my $count = 0; while ($stop ne join(' ',@colkey)) { CalcCol($#colheads); my $key = join(' ',@colkey); # next if !defined $columnheaders{$key}; $cols[$count] = $key; $count++; } #print '
',main::Dumper(@cols),'
'; #display print ''; my $datacount; #print the column headers my $count = 0; my @colkeys; foreach my $h (@colheads) { $datacount = 0; print ''; print ''; print ""; foreach my $key (@cols) { next if !defined $columnheaders{$key}; $datacount++; my @tmp = split(' ', $key); foreach (@datacols) { print ''; } } print ''; $count++; } #print the row heads & data col heads print ''; print ''; for (my $i = 0; $i < $datacount;$i++) { foreach my $h (@datacols) { print ""; } } print ''; #print the row headers and data; my @rowheader; my @rowkey; my $rowcount; my $count = 0; my $stop = ''; foreach (@rowheads) { $rowkey[$count] = 0; $stop = $stop.$#{$names{$rowheads[$count]}}.' '; $count++; } chop $stop; my $first = 1; while (join(' ',@rowkey) ne $stop) { CalcRow($#rowheads); my $rowOK = 0; my $count = 0; foreach my $h (@rowheads) { $rowheader[$count] = ${$names{$h}}[$rowkey[$count]]; $count++; } my $rowstr = ''; foreach my $k (@cols) { next if !defined $columnheaders{$k}; my $data = $values{join(' ',@rowkey).' '.$k}; my @data; if (defined($data)) { @data = @{$data}; $rowOK = 1; } else { foreach (@datacols) { push @data, undef; } } $rowstr = $rowstr.''; } if ($rowOK) { print $rowstr,''; } } sub CalcRow { my $pos = shift; if ($pos == 0) { $rowkey[0]++ if $rowkey[0] <= $#{$names{$rowheads[0]}}; return 0; } else { if ($rowkey[$pos] >= $#{$names{$rowheads[$pos]}}) { #PRINT TOTAL LINE HERE $rowkey[$pos] = 0; CalcRow($pos-1); } else { $rowkey[$pos]++; return 0; } } return 1; } sub CalcCol { my $pos = shift; if ($pos == 0) { $colkey[0]++ if $colkey[0] <= $#{$names{$colheads[0]}}; return 0; } else { if ($colkey[$pos] >= $#{$names{$colheads[$pos]}}) { #PRINT TOTAL LINE HERE $colkey[$pos] = 0; CalcCol($pos-1); } else { $colkey[$pos]++; return 0; } } return 1; } print '
$h'.${$names{$h}}[$tmp[$count]].'
',join('',@rowheads),'$h
'.join('',@rowheader).''.join('',@data).'
'; #print '

columnheaders:

',main::Dumper(%columnheaders),'

'; #print '

stop: ',main::Dumper($stop); #print '

stop: ',main::Dumper(join(' ',@rowkey)); #print '

NAMES: ',main::Dumper(%names),'

'; #print 'VALUES: ',main::Dumper(%values),'

'; #print 'ORDINALS: ',main::Dumper(%ordinals),'

'; sub GetKey { my $count = 0; my @key; foreach my $val (@_) { if (defined $ordinals{$pivots[$count].$val}) { push @key, $ordinals{$pivots[$count].$val}; } else { my $o = push @{$names{$pivots[$count]}},$val; $o--; $ordinals{$pivots[$count].$val} = $o; push @key, $o; } $count++; } return \@key; } 1;