Your main point of confusion seems to be in the inner loop. (Well, that and your lack of 'use strict'!) You are looking for inactive records, and doing something confusing with each occurence of those records. If I understand your problem description correctly, you should instead search for *active* records, and if you see *any*, then it does not matter how many there are - it means that the user is active, so just skip that user.

Here is that loop, recast but not tested (because I don't have 'db-common.sub'):

USER: while ( $pointer = $sth->fetchrow_hashref ) { $username = $pointer->{'username'}; # Connect to jobs DB and get the entries that match the username # XXX Changed from != to =, and selecting only the count. $SQL2 = "SELECT count(*) FROM $jobstable" . " where username = '$username' and active = 'yes'"; &Do_SQL2; $pointer2 = $sth2->fetchrow_hashref; if ( $pointer2->{'count(*)'} > 0 ) { print "Skipping active user '$username'\n"; next USER; } $userdirectory = $rootpath . $username; print "Directory '$userdirectory' to be deleted\n"; File::Path::rmtree( $userdirectory ); }

Because the amount of data is relatively small, if I was writing this from scratch, I would approach the problem quite differently. The code below makes 2 DB calls instead of 30,000+ calls, and (with the *highly* recommended SQLite and DBD::SQLite) is fully testable on your desktop PC.
Working, tested code:

#!/usr/bin/perl use strict; use warnings; use DBI; use File::Path; my $really_delete_the_directories = 1; #require 'db-common.sub' or die "Error loading db-common.sub"; #my $rootpath = '/usr/www/users/me/reg/'; my $rootpath = './'; die if not -d $rootpath; my $regtype = 'ch'; my $yeartodelete = '2002'; my $dbh; #&Conn_to_DB; # Something to initialize $dbh, I hope! TEST_STUFF: { my $sqlite_db_name = 'pm_666415.db'; unlink $sqlite_db_name or die if -e $sqlite_db_name; $dbh = DBI->connect("dbi:SQLite:dbname=$sqlite_db_name") or die; # Create data just for testing. my @db_setup = grep { /\S/ } split /(?:#.+)?\n/, <<'END_OF_SQL'; CREATE TABLE registrations ( username CHAR(10), regtype CHAR(2), datea +dded CHAR(8) ); INSERT INTO registrations VALUES( 'Able' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Baker' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Charlie', 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Roger' , 'ch', '20020101' ); INSERT INTO registrations VALUES( 'Fox' , 'zz', '20020101' ); # Wr +ong regtype INSERT INTO registrations VALUES( 'Dog' , 'ch', '20030101' ); # No +t in date range CREATE TABLE joblistings ( username CHAR(10), active CHAR(3) ); INSERT INTO joblistings VALUES( 'Able' , 'yes' ); # Has both yes INSERT INTO joblistings VALUES( 'Able' , 'no' ); # and no INSERT INTO joblistings VALUES( 'Baker' , 'yes' ); INSERT INTO joblistings VALUES( 'Charlie', 'no' ); INSERT INTO joblistings VALUES( 'Roger' , 'no' ); INSERT INTO joblistings VALUES( 'Fox' , 'yes' ); INSERT INTO joblistings VALUES( 'Dog' , 'no' ); END_OF_SQL # I expect Charlie and Roger to be removed. $dbh->do($_) or die for @db_setup; mkdir $_ for qw( Able Baker Charlie Roger Fox Dog ); } my $sql1 = <<'END_OF_SQL'; SELECT username FROM registrations WHERE regtype = ? AND dateadded LIKE ? END_OF_SQL my @parms1 = ( $regtype, '%'.$yeartodelete.'%' ); my $jobstable = ( $regtype eq 'ch' ) ? 'joblistings' : 'jobswanted'; my $sql2 = <<"END_OF_SQL"; SELECT username FROM $jobstable WHERE active = 'yes' GROUP BY username END_OF_SQL # All data will fit into memory, so slurp in: # 1) an array of all the usernames that were # registered in some past year, and # 2) an array of all the users considered "active". my @registered_users = get_all_of_a_single_column( $dbh, $sql1, @parms +1 ); my @active_users = get_all_of_a_single_column( $dbh, $sql2 ); $dbh->disconnect; # make a lookup table of the actives my %active_user = map { $_ => 1 } @active_users; #use Data::Dumper; #print Dumper \@registered_users, \@active_users; # Only consider inactive users my @users_to_remove = grep { not $active_user{$_} } @registered_users; # Generate a list of those users directories. my @user_dirs_to_remove = map { $rootpath . $_ } @users_to_remove; # Any dirs already deleted, we remove from the list. @user_dirs_to_remove = grep { -d $_ } @user_dirs_to_remove; print "Going to remove directories:\n ", join("\n ", @user_dirs_to_remove), "\n"; if ($really_delete_the_directories) { File::Path::rmtree( \@user_dirs_to_remove, { verbose => 1 } ); } sub get_all_of_a_single_column { my ( $dbh, $sql, @params ) = @_; my $all_rows_aref = $dbh->selectall_arrayref( $sql, undef, @params ) or die; # Return a list of the first column of each row. return map { $_->[0] } @{ $all_rows_aref }; }


In reply to Re: Need help with loops and 3 tables by Util
in thread Need help with loops and 3 tables by htmanning

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.