Объединение неуникальных значений вместе с уникальным полем в PowerShell - PullRequest
1 голос
/ 06 ноября 2019

У меня есть следующий набор запросов, которые извлекают набор данных, объединяют его, так что я просто получаю уникальные значения и добавляю число к каждому из них (чтобы я мог выбрать этот конкретный элемент позже).

$allMoveRequests = Get-MoveRequest -DomainController server | 
    select Alias,Status,TargetDatabase,BatchName 

$optNum=1
$AllMoveBatches = @($allMoveRequests | Sort-Object -Property BatchName | 
    Select-Object BatchName,TargetDatabase -Unique) |
    Select @{Name="Option";Expression={$optNum;$optNum++}},BatchName,TargetDatabase

$AllMoveBatches | Format-Table -AutoSize | Out-String|% {Write-Host $_}

Возвращает:

Option BatchName TargetDatabase
------ --------- --------------
1      Batch1    Database1
2      Batch2    Database2

и т. Д. Это работает, как и должно, но я хотел бы добавить значение Status из этих пакетов, объединенное, когда существует более одного, а не создавать повторяющиеся записи. Например, если я просто добавлю Status во второй бит кода, я получу:

Option BatchName TargetDatabase Status
------ --------- -------------- ------
1      Batch1    Database1      Completed
2      Batch1    Database1      In Progress
3      Batch2    Database2      Completed

, в то время как в идеале мне хотелось бы:

Option BatchName TargetDatabase Status
------ --------- -------------- ------
1      Batch1    Database1      Completed,InProgress
2      Batch2    Database2      Completed

попытался использовать выражение в операторе select для запроса всех соответствующих записей статуса и применения к ним -Unique, но он просто возвращает все записи статуса во всех пакетах, а не только те, которые относятся к текущей строке пакета.

Есть ли способ достичь этого?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Это не красиво, и это может быть не очень производительно с большим количеством данных, но вот один из способов сделать это ...

Во-первых, давайте создадим несколько примеров данных:

$data = @(
    (new-object PSObject -Property ([ordered] @{
        "BatchName"      = "Batch1"
        "TargetDatabase" = "Database1"
        "Status"         = "Completed"
    })),
    (new-object PSObject -Property ([ordered] @{
        "BatchName"      = "Batch1"
        "TargetDatabase" = "Database1"
        "Status"         = "In Progress"
    })),
    (new-object PSObject  -Property ([ordered] @{
        "BatchName"      = "Batch2"
        "TargetDatabase" = "Database2"
        "Status"         = "Completed"
    }))
)

сейчас, обработайте его:

Set-Variable -Name "optNum" -Option AllScope -Value 1
$results = @( $data | group-object BatchName, TargetDatabase ) `
    | select-object @{Name="Option";Expression={$optNum; $optNum++}},
                    @{Name="BatchName";Expression={$_.Group[0].BatchName}},
                    @{Name="TargetDatabase";Expression={$_.Group[0].TargetDatabase}},
                    @{Name="Status";Expression={$_.Group.Status -join ", "}} `
    | sort-object -Property BatchName

и покажите результат:

PS> $results

Option BatchName TargetDatabase Status
------ --------- -------------- ------
     1 Batch1    Database1      Completed, In Progress
     2 Batch2    Database2      Completed

Что он делает, это группировка , чтобы выбрать уникальные комбинации BatchName и DatabaseNameа затем для получения результатов он выбирает BatchName и DatabaseName из первого элемента в каждой группе и объединяет все свойства Status из элементов в этой группе (вы также можете обработать состояния в выражении состояния, если вы хотите, например, отсортировать, отфильтруйте или удалите их в каждой группе).

Обратите внимание, что я переместил ваш исходный sort-object BatchName в конец конвейера. Нет смысла сортировать, скажем, 1000 объектов только для того, чтобы выбросить половину из них - вы могли бы также отсортировать в конце.

И я мог только заставить ваш счетчик «Option» работать, используя Set-Variable, чтобы сделатьAllScope, поскольку $optNum++ не увеличивал переменную должным образом, когда я использовал $optNum = 1 для ее инициализации.

1 голос
/ 07 ноября 2019
Ответ

mclayton должен быть принят, но вот несколько более краткая версия, которая использует одну из моих любимых идиом Powershell: Foreach с -Begin scriptblock {$i=1}, который выполняется только один раз.

[pscustomobject]@{BatchName = 'Batch1';TargetDatabase='Database1';Status='Completed'},
[pscustomobject]@{BatchName = 'Batch1';TargetDatabase='Database1';Status='In Progress'},
[pscustomobject]@{BatchName = 'Batch2';TargetDatabase='Database2';Status='Completed'} |
    Group BatchName, TargetDatabase | 
    %{$i=1}{ [pscustomobject]@{Option = $i++ 
            BatchName = $_.Group[0].BatchName
            TargetDatabase = $_.Group[0].TargetDatabase
            Status = $_.Group.Status -join ','}
    } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...