编辑更清晰:
我将从数据库中获取2个查询并将它们存储为AoH。这2个查询是:
select
ip_address,
testnet,
t.email as email,
owner,
hr_manager_login as manager
from
lab_view
JOIN CMN_INT.AK_EMPLOYEE on owner = login
JOIN testnets t on t.name = testnet
where
DIVISION like 'TERM%' and TERM_DATE is not null
order by owner
和select login from CMN_INT.AK_EMPLOYEE where DIVISION = q[Terminated Employees]
对于我原来的测试,我不会潜入开放/使用DBI,因此我使用了虚拟数据。我的$ qr是我从第一个查询得到的一个例子,我的$ qr2是我从第二个查询得到的一个例子。我想查看第一个AoH中的Manager值是否在第二个(终止员工)AoH中找到。如果找到,则经理是已终止的员工,其名称不应推送到%经理。我尝试通过将下面的foreach代码插入到我的第一个foreach代码中来测试它,但它不起作用,因为Harry仍然被推送和打印。
foreach my $emp2 (@$qr2){
if ($emp->{Manager} ne $emp2->{Login}){
$manager{$emp->{Manager}} = 1; #capture all managers not also terminated related to $name. Done this way for when $name is undef
}
}
我还尝试在第二个foreach之前将$ emp - > {Manager}分配给一个变量,然后使用if($ M ne $ emp2 - > {Login}),但这也没有用。
下面是我的测试代码的第一部分,其中包含我将运行的查询的虚拟数据,减去所有的elsifs :)
my $qr = [
{IP=>'X.Y.Z.51',Testnet=>'bos-por-leg',Owner=>'Edmund', Email => 'bosemail', Manager => 'Tod'},
{IP=>'X.Y.Z.52',Testnet=>'bos-por-2',Owner=>'Edmund', Email => 'boemail2',Manager => 'Tod'},
{IP=>'X.Y.Z.53',Testnet=>'bos-por-leg',Owner=>'Edmund', Email => 'bosemail',Manager => 'Tod'},
{IP=>'X.Y.Z.54',Testnet=>'sqa',Owner=>'Richard', Email => 'sqaemail',Manager => 'Harry'},
{IP=>'X.Y.Z.55',Testnet=>'sqa',Owner=>'Richard', Email => 'sqaemail',Manager => 'Harry'},
{IP=>'X.Y.Z.56',Testnet=>'fll-pro',Owner=>'Larry', Email => 'fllemail',Manager => 'Moe'},
{IP=>'X.Y.Z.57',Testnet=>'fll-pro', Owner=>'', Email => 'fllemail',Manager => 'Tod'},
{IP=>'X.Y.Z.58',Testnet=>'fll-pro2', Owner=>'', Email => 'flemail2', Manager => 'Curly'},
];
my $qr2 = [{Login => 'Tom'},
{Login => 'Dick'},
{Login => 'Harry'},
];
my $len = scalar @$qr;
my $l = $len;
my $a = @$qr[0]->{Owner};
func ($a);
my %ip;
my %test;
my $name;
my %manager;
my $ip_ref;
my $test_ref;
my $man_ref;
sub func{
foreach my $emp (@$qr) {
if ($l > 1 && $emp->{Owner} eq $a) {
$name = $emp->{Owner} || 'Undefined'; #to use with email as $a will change as cycle thru
$ip{$emp->{IP}} = $emp->{Testnet}; #capture all IPs related to owner $name
$test{$emp->{Testnet}} = $emp->{Email}; #capture unique testnets only related to owner $name
foreach my $emp2 (@$qr2){
if ($emp->{Manager} ne $emp2->{Login}){
$manager{$emp->{Manager}} = 1; #capture all managers not also term related to $name. Done this way for when $name is undef
}
}
$l--; #to cycle thru array until reach last row
}
}
}
sub mail_func{
my $n = shift; #user
my $i = shift; #ips
my $t = shift; #testnets
my $m = shift; #managers (multiple if owner is undef) --> to field
print "User name is: $n\n";
my @to_list;
foreach my $value (values %{$t}){
if ($value ne 'bosemail'){
if (grep {$value} @to_list){next;}
else {push(@to_list,$value . '@email.com');}
}
}
foreach my $key (keys %{$m}){push(@to_list,$key . '@email.com');}
print "@to_list\n";
my @body;
while ( my ( $key, $value ) = each %{$i} ) {
my $b = "IP " . $key . " : Testnet " . $value . "\n";
push (@body, $b);
}
print "@body\n";
}
在测试中,我得到:
User name is: Richard
[email protected] [email protected] ##Harry shouldn't be added
IP X.Y.Z.54 : Testnet sqa
IP X.Y.Z.55 : Testnet sqa
我很欣赏有关如何纠正的所有意见。如果您需要更多代码,请告诉我们。另外需要注意的是,终止的员工名单很长,所以我猜我甚至不应该通过循环方法将一个AoH中的每个值与另一个AoH中的每个值进行比较,但这就是我所知道的全部:)我我试图看看是否有办法做我想要的只使用1个查询。谢谢。
除非我错过了一些明显的东西,否则我认为你的事情太复杂了。
以下适用于我。
警告:它使用'smartmatch operator'来搜索数组中的元素。 AFAIK此功能仍被视为“实验性”。其他人可能会评论该功能的状态 - 或建议更合适的替代方案。
use strict;
use warnings;
use feature 'say';
my $qr = [
{IP=>'X.Y.Z.51',Testnet=>'bos-por-leg',Owner=>'Edmund', Email => 'bosemail', Manager => 'Tod'},
{IP=>'X.Y.Z.52',Testnet=>'bos-por-2',Owner=>'Edmund', Email => 'boemail2',Manager => 'Tod'},
{IP=>'X.Y.Z.53',Testnet=>'bos-por-leg',Owner=>'Edmund', Email => 'bosemail',Manager => 'Tod'},
{IP=>'X.Y.Z.54',Testnet=>'sqa',Owner=>'Richard', Email => 'sqaemail',Manager => 'Harry'},
{IP=>'X.Y.Z.55',Testnet=>'sqa',Owner=>'Richard', Email => 'sqaemail',Manager => 'Harry'},
{IP=>'X.Y.Z.56',Testnet=>'fll-pro',Owner=>'Larry', Email => 'fllemail',Manager => 'Moe'},
{IP=>'X.Y.Z.57',Testnet=>'fll-pro', Owner=>'', Email => 'fllemail',Manager => 'Tod'},
{IP=>'X.Y.Z.58',Testnet=>'fll-pro2', Owner=>'', Email => 'flemail2', Manager => 'Curly'},
];
my $qr2 = [{Login => 'Tom'},
{Login => 'Dick'},
{Login => 'Harry'},
];
my @dismissed = map { $_->{Login} } @$qr2;
my @eligible = grep { !($_->{Manager} ~~ @dismissed) } @$qr;
say $_->{Testnet}, ', ', $_->{Email} foreach @eligible;
备用数据库查询
由于您使用Perl而不是DBI标记了问题,因此这是括号 - 但我认为值得注意。
您询问:
我也试图看看是否有办法只使用1个查询来做我想要的事情
我认为有 - 使用NOT IN运算符。类似于以下内容可能会起作用 - 尽管您可能需要稍微改变语法,具体取决于您使用的数据库服务器。
简单地为你的WHERE
条款添加另一个条件,所以
where
DIVISION like 'TERM%' and TERM_DATE is not null
会成为
where
DIVISION like 'TERM%' and TERM_DATE is not null
AND
hr_manager_login NOT IN (select login from CMN_INT.AK_EMPLOYEE where DIVISION = q[Terminated Employees])
如果已终止员工的数量非常长(您的亲密度很长,但未详细说明多长时间),使用NOT IN
可能会对性能产生影响,但我认为这可能并非如此。