【问题标题】:Inner Join in PowerShell (without SQL)PowerShell 中的内部联接(无 SQL)
【发布时间】:2017-01-30 12:31:08
【问题描述】:

我们如何在 PowerShell 或 PowerCLI 中创建 Inner-JoinCross-Join

尽管我是 PowerCLI/PowerShell 的新手,但我对它们有基本的了解,但实际上花了 2 天时间试图弄清楚这一点,浏览了大量文档和博客,但无济于事。

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

Get-Content File.txt 

得到:

Output1 或 Table1 是

名称:ABC
组:坏
政策:很好

名称:雷迪
组:好
政策:疯狂

等等等等。

其中有 100 个,显然不仅仅是名称、组、策略这 3 个元素。


表2/输出2

名称:ABC
限制:10
使用:5

名称:雷迪
限制:20
使用:1

等等等等。

100 个。


还有 13 个这样的文本文件表,所有的“名称”都是唯一的。

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

我最明显的想法是类似于加入,即使我必须一次做 1 个,但即使我不知道该怎么做。

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

如果是,有没有一种方法可以在它为空的地方组合字段?

如果不清楚我希望得到什么类型的结果,它看起来类似于这样:

名称:ABC
组:坏
政策:很好
限制:10
使用:5


名称:雷迪
组:好
政策:疯狂
限制:20
使用:1

【问题讨论】:

    标签: powershell join inner-join powercli


    【解决方案1】:

    Paweł Dyl provided you a solution 根据你的两张桌子。但是,您可能需要一个通用的解决方案,您不必自己指定每个属性的名称。


    我会将每个表组合成一个数组。使用 Group-Object cmdlet 对 Name 属性上的表进行分组。遍历每个组并使用属性创建一个 PsObject:

    $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'}
    
    $allTables = $table1 + $table2
    
    $allTables | group Name | Foreach {
        $properties = @{}
        $_.Group | Foreach {
            $_.PsObject.Properties | Where Name -ne 'Name' | Foreach {
                $properties +=  @{
                    "$($_.Name)" = "$($_.Value)"
                }
            }
        }
        $properties += @{Name = $_.Name}
        New-Object PSObject –Property $properties
    }
    

    输出:

    Group  : Bad
    Policy : Great
    Name   : Abc
    Limit  : 10
    used   : 5
    
    Group  : Good
    Policy : MAD
    Name   : redi
    Limit  : 20
    used   : 1
    

    【讨论】:

    • 好,赞成 :) 我还添加了非泛型哈希连接。
    • 您可能必须解析您的文本文件 - 如果您遇到问题,可以开始另一个问题。您可以使用| Select-Object name, Group, ... 指定您选择的顺序并始终将名称放在首位。请考虑接受答案。
    • 谢谢,我想只是确认的是,如果我可以 Get-content file.txt 并从 $table1 = 开始添加您的代码,然后将其调整到足以匹配我的表格规格因为我不想只需键入所有不同的键值对,因为它违背了目的,并且当另一个“名称”添加到整个列表中时不会说,我再次运行代码
    【解决方案2】:

    您可以按如下方式使用简单的循环连接:

    $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}
                        }
                    }
                }
    

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

    $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}
        }
    }
    

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

    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
    

    你也可以级联调用:

    $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
    

    【讨论】:

    • 做的工作,但我添加了一个更通用的解决方案:-)
    • 谢谢...但我想知道是否必须输入长长的键值对列表? ..... 会有 $table1= Get-Content file1.txt |Select Name etc 并且 $table2 和 3 etc 是相似的;是否可以用 [pscustomobject ] 和键值对替换上面的 $table1 .....这也可以用超过 2 个表来完成吗?
    • 添加了另一个示例。
    【解决方案3】:

    所以我找到了一个更合适的答案,它使用了下面定义的 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
    

    $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
    

    直到我全部完成

    【讨论】:

      【解决方案4】:
      $Table1 | Join $Table2 -Using Name
      $Table1 | Join $Table2 #Cross Join
      

      见:In Powershell, what's the best way to join two tables into one?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-09
        • 1970-01-01
        相关资源
        最近更新 更多