在PowerShell中进行内部联接(无SQL)

Adi*_*ilZ 5 powershell join inner-join powercli

我们如何在PowerShell或PowerCLI中制作Inner-Join东西Cross-Join

尽管我对PowerCLI / PowerShell并不陌生,但我确实对此有一个基本的了解,但实际上花了两天的时间来弄清楚这一点,无数次浏览大量文档和博客。

我真正想知道的是输入命令后是否

Get-Content File.txt 
Run Code Online (Sandbox Code Playgroud)

并得到:

输出1或表1为

姓名:Abc
组:坏
政策:很棒

名称:redi
组:好 
政策:MAD

等等等

其中有100多个,而且显然每个名称,组,策略这3个元素都不止。


表2 /输出2

姓名:Abc
上限:10
用过的:5

名称:redi
上限:20
用过的:1

等等等

其中有数百个。


以及另外13个这些文本文件表,它们的“名称”都是唯一的。

最后如何使用Name和其他所有元素将其组合为一个输出?

我最明显的想法是有些类似的加入,即使我一次必须做一次,但即使我也无法弄清楚该怎么做。

无论如何,在PowerShell本身中是否可以执行此操作而无需我使用Python或SQL?

如果是,是否有一种方法可以将字段合并为空?

如果不清楚结果是什么类型,我希望它看起来类似于以下内容:

姓名:Abc
组:坏
政策:很棒
上限:10
用过的:5


名称:redi
组:好 
政策:MAD
上限:20
用过的:1

Paw*_*Dyl 5

您可以使用简单的循环连接,如下所示:

$table1 = [pscustomobject]@{Name='Abc';Group='Bad';Policy='Great'},[pscustomobject]@{Name='redi';Group='Good ';Policy='MAD'}
$table2 = [pscustomobject]@{Name='Abc';Limit=10;used=5},[pscustomobject]@{Name='redi';Limit=20;used=1}

$table1 | % { 
                foreach ($t2 in $table2) {
                    if ($_.Name -eq $t2.Name) {
                        [pscustomobject]@{Name=$_.Name;Group=$_.Group;Policy=$_.Policy;Limit=$t2.Limit;Used=$t2.Used}
                    }
                }
            }
Run Code Online (Sandbox Code Playgroud)

假设键的唯一性,您还可以使用更快的哈希表方法:

$hashed = $table1 | group Name -AsHashTable
$table2 | % {
    $matched = $hashed[$_.Name]
    if ($matched) {
        [pscustomobject]@{Name=$matched.Name;Group=$matched.Group;Policy=$matched.Policy;Limit=$_.Limit;Used=$_.Used}
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用通用解决方案并将其包装在函数中。它按属性名称匹配记录:

function Join-Records($tab1, $tab2){
    $prop1 = $tab1 | select -First 1 | % {$_.PSObject.Properties.Name} #properties from t1
    $prop2 = $tab2 | select -First 1 | % {$_.PSObject.Properties.Name} #properties from t2
    $join = $prop1 | ? {$prop2 -Contains $_}
    $unique1 = $prop1 | ?{ $join -notcontains $_}
    $unique2 = $prop2 | ?{ $join -notcontains $_}


    if ($join) {
        $tab1 | % {
            $t1 = $_
            $tab2 | % {
                $t2 = $_
                foreach ($prop in $join) {
                    if (!$t1.$prop.Equals($t2.$prop)) { return; }
                }
                $result = @{}                
                $join | % { $result.Add($_,$t1.$_) }
                $unique1 | % { $result.Add($_,$t1.$_) }
                $unique2 | % { $result.Add($_,$t2.$_) }
                [PSCustomObject]$result
            }
        }
    }
}

$table1 = [pscustomobject]@{Name='Abc';Group='Bad';Policy='Great'},
    [pscustomobject]@{Name='redi';Group='Good ';Policy='MAD'},
    [pscustomobject]@{Name='Not joined';Group='Very bad';Policy='Great'}
$table2 = [pscustomobject]@{Name='Abc';Limit=10;used=5},
    [pscustomobject]@{Name='redi';Limit=20;used=1},
    [pscustomobject]@{Name='redi';Limit=20;used=2}

#name is only common property, records joined by name
Join-Records $table1 $table2

#example2
$test1 = [pscustomobject]@{A=1;B=1;C='R1'},
    [pscustomobject]@{A=1;B=2;C='R2'},
    [pscustomobject]@{A=2;B=2;C='R3'}

$test2 = [pscustomobject]@{A=1;B=1;D='R4'},
    [pscustomobject]@{A=3;B=2;D='R5'},
    [pscustomobject]@{A=4;B=2;D='R6'}

Join-Records $test1 $test2 #joined by two common columns - A and B
Run Code Online (Sandbox Code Playgroud)

您还可以级联调用:

$test1 = [pscustomobject]@{A=1;B=1;C='R1'},
    [pscustomobject]@{A=1;B=2;C='R2'},
    [pscustomobject]@{A=2;B=2;C='R3'}

$test2 = [pscustomobject]@{A=1;B=1;D='R4'},
    [pscustomobject]@{A=3;B=2;D='R5'},
    [pscustomobject]@{A=4;B=2;D='R6'}

$test3 = [pscustomobject]@{B=1;E='R7'},
    [pscustomobject]@{B=2;E='R8'},
    [pscustomobject]@{B=3;E='R9'}

#first join by common A and B, then join result by common B
Join-Records (Join-Records $test1 $test2) $test3
Run Code Online (Sandbox Code Playgroud)


Adi*_*ilZ 1

所以我找到了一个更合适的答案,它使用下面定义的join-Object函数:

您可以在https://github.com/RamblingCookieMonster/PowerShell/blob/master/Join-Object.ps1访问它

我真正要做的就是将我的输出定义为 $A 和 $B 和 $C 等等,然后

$Join1=  Join-Object -Left $A -Right $B -LeftJoinProperty Name - RightJoinProperty Name
Run Code Online (Sandbox Code Playgroud)

做了 $Join2 然后 3 依此类推,直到我全部完成

$Join2 = Join-Object -Left $Join1 -Right $C -LeftJoinProperty Name -RightJoinProperty Name

$Join3 = Join-Object -Left $Join2 -Right $D -LeftJoinProperty Name -RightJoinProperty Name

$Join4 = Join-Object -Left $Join3 -Right $E -LeftJoinProperty Name -RightJoinProperty Name
Run Code Online (Sandbox Code Playgroud)

直到我完成这一切