use strict; my @views = ( 'view0', 'view1', 'view2', 'view3' ); my %columns = ( 'view0' => [qw(buffersize size value)], 'view1' => [qw(buffersize size value)], 'view2' => [qw(buffersize size value)], 'view3' => [qw(buffersize size value)] ); print build_query(\@views, \%columns), "\n"; my $last; sub build_query { my($views, $columns) = @_; my $first = shift @{$views}; $last = $first; return join(' full outer join ', $first, view_on_clauses($views, $columns)); } sub view_on_clauses { my($views, $columns) = @_; return map { join(' ', $_, 'on', and_clause($_, $columns)) } @{$views}; } sub and_clause { my($view, $columns) = @_; return join(' and ', equality_clauses($view, $columns)); } sub equality_clauses { my($view, $columns) = @_; my @equality_clauses = ( ); # Convert map into explicit for loop because we need to # merge together two different arrays. If the column names # are always the same, then map can be used. for (my $i = 0; $i < @{$columns->{$view}} - 1; ++$i) { push @equality_clauses, $last . '.' . $columns->{$last}[$i] . '=' . $view . '.' . $columns->{$view}[$i]; } $last = $view; return @equality_clauses; }