需要将 AoH 中的一个值与第二个 AoH 中的另一个值进行比较
Need to compare one value in AoH to another value in a second AoH
编辑更清楚:
我将从数据库中获取 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]
对于我最初的测试,我不打算深入研究 opening/using DBI,所以我使用了虚拟数据。我的 $qr 是我从第一个查询中得到的一个例子,我的 $qr2 是我从第二个查询中得到的一个例子。我想查看第一个 AoH 中的 Manager 值是否在第二个(已离职员工)AoH 中找到。如果找到,则该经理是已离职的员工,不应将其姓名推送给 %manager。我尝试通过将下面的 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
sqaemail@email.com Harry@email.com ##Harry shouldn't be added
IP X.Y.Z.54 : Testnet sqa
IP X.Y.Z.55 : Testnet sqa
感谢所有关于如何更正的意见。如果您需要更多代码,请告诉我。还要注意,终止的员工列表很长,所以我猜我什至不应该通过循环方法将一个 AoH 中的每个值与另一个 AoH 中的每个值进行比较,但这就是我所知道的:)我我还想看看是否有办法只使用 1 个查询来做我想做的事情。谢谢。
除非我遗漏了一些明显的东西,否则我认为你把事情搞得太复杂了。
以下适合我。
警告: 它使用 'smartmatch operator' 来搜索数组中的元素。据我所知,此功能仍被视为 'experimental'。其他人可能能够评论该功能的状态 - 或者建议更合适的替代方案。
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 标记了问题,所以这是附加的 - 但我认为仍然值得注意。
您问的是:
I am trying to also see if there is a way to do what I want using only
1 query
我认为有 - 使用 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])
如果被解雇的员工人数 非常长(您暗示它是 'quite long' - 但没有具体说明多长时间)可能会对性能产生影响使用 NOT IN
,但我认为这里可能不是这种情况。
编辑更清楚:
我将从数据库中获取 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]
对于我最初的测试,我不打算深入研究 opening/using DBI,所以我使用了虚拟数据。我的 $qr 是我从第一个查询中得到的一个例子,我的 $qr2 是我从第二个查询中得到的一个例子。我想查看第一个 AoH 中的 Manager 值是否在第二个(已离职员工)AoH 中找到。如果找到,则该经理是已离职的员工,不应将其姓名推送给 %manager。我尝试通过将下面的 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
sqaemail@email.com Harry@email.com ##Harry shouldn't be added
IP X.Y.Z.54 : Testnet sqa
IP X.Y.Z.55 : Testnet sqa
感谢所有关于如何更正的意见。如果您需要更多代码,请告诉我。还要注意,终止的员工列表很长,所以我猜我什至不应该通过循环方法将一个 AoH 中的每个值与另一个 AoH 中的每个值进行比较,但这就是我所知道的:)我我还想看看是否有办法只使用 1 个查询来做我想做的事情。谢谢。
除非我遗漏了一些明显的东西,否则我认为你把事情搞得太复杂了。
以下适合我。
警告: 它使用 'smartmatch operator' 来搜索数组中的元素。据我所知,此功能仍被视为 'experimental'。其他人可能能够评论该功能的状态 - 或者建议更合适的替代方案。
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 标记了问题,所以这是附加的 - 但我认为仍然值得注意。
您问的是:
I am trying to also see if there is a way to do what I want using only 1 query
我认为有 - 使用 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])
如果被解雇的员工人数 非常长(您暗示它是 'quite long' - 但没有具体说明多长时间)可能会对性能产生影响使用 NOT IN
,但我认为这里可能不是这种情况。