需要将AoH中的一个值与第二个AoH中的另一个值进行比较

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了需要将AoH中的一个值与第二个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]

对于我原来的测试,我不会潜入开放/使用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
";
    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
";
    my @body;
    while ( my ( $key, $value ) = each %{$i} ) {
        my $b = "IP " . $key . " : Testnet " . $value . "
";
        push (@body, $b);
    }
    print "@body
";
}

在测试中,我得到:

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'来搜索数组中的元素。 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可能会对性能产生影响,但我认为这可能并非如此。

以上是关于需要将AoH中的一个值与第二个AoH中的另一个值进行比较的主要内容,如果未能解决你的问题,请参考以下文章

您可以将一个表中具有另一个表的列名的列与第二个表链接吗

将基表值与第二个表的值之和与group by进行比较

如果一个列值与第二个 df 列值匹配,我有两个数据框过滤 onmatch 列行

Dropbox 风格的 URL,不使用哈希或参数

将第一个文件的第一列与第二个文件中的行匹配,然后将第二个文件中匹配行的最后一列插入第一个文件中的新第一列

如何编写 BigQuery/SQL 查询以将一个表中的列的平均值与第二个/另一个表中的列相除