re-arrange 并结合 powershell 自定义 objects

re-arrange and combine powershell custom objects

我有一个系统当前正在从一个即将被替换的单独系统生成的 CSV 文件中读取数据。

导入的 CSV 文件如下所示

PS> Import-Csv .\SalesValues.csv
Sale Values AA BB
----------- -- --
10          6  5
5           3  4
3           1  9

为了替换这个过程,我希望生成一个看起来与上面的 CSV 相同的 object,但我不想继续使用 CSV 文件。

我已经有一个脚本可以从我们的数据库中读取数据并提取我需要使用的数据。我不会详细说明这一点之前相当长的脚本,但实际上它看起来像这样:

$SQLData = Custom-SQLFunction "SELECT * FROM SALES_DATA WHERE LIST_ID = $LISTID"

$SQLData 将包含 ~5000+ 我需要查询的数据行 object。

其中一个 DataRow object 看起来像这样:

lead_id                 : 123456789
entry_date              : 26/10/2018 16:51:16
modify_date             : 01/11/2018 01:00:02
status                  : WRONG
user                    : mrexample
vendor_lead_code        : TH1S15L0NGC0D3
source_id               : A543212
list_id                 : 333004
list_name               : AA Some Text
gmt_offset_now          : 0.00
SaleValue               : 10

list_name 将以 AABB.

为前缀

SaleValue 可以是 3 及以上的任何整数,但实际上极不可能高于 100(因为这是每月捐款)并且在绝大多数情况下将是 3、5、10 之一出现次数。

我已经有一个脚本可以获取 list_name 的内容,创建我需要使用的数据并将其填充到两个单独的 psobjects($AASalesValues$BBSalesValues) 整理了数据集中 'SaleValue' 的总数。

因为我无法可靠地预测任何 SaleValue 的值,所以我必须像这样动态创建 psobjects 属性

foreach ($record in $SQLData) {
    if ($record.list_name -match "BB") {
        if ($record.SaleValue -gt 0) {
            if ($BBSalesValues | Get-Member -Name $($record.SaleValue) -MemberType Properties) {
                $BBSalesValues.$($record.SaleValue) = $BBSalesValues.$($record.SaleValue)+1
            } else {
                $BBSalesValues | Add-Member -Name $($record.SaleValue) -MemberType NoteProperty -Value 1
            }
        }
    }    
}

两个结果 object 看起来像这样:

PS> $AASalesValues
10  5 3 50
--  - - --
17 14 3  1

PS> $BBSalesvalues
 3 10  5 4
 - --  - -
36 12 11 1

我现在有了我需要的数据,但是我需要以复制 CSV 格式的方式对其进行格式化,以便我可以将其直接传递给另一个现有的 powershell配置为期望 CSV 格式的数据的脚本,但我不想将数据写入文件。

我更愿意将其直接传递到脚本的下一部分。

最终我想要做的是生成一个新的 object/some 输出,它看起来像此 post.

顶部的 Import-Csv 命令的输出

我想要一个新的 object,比如 $OverallSalesValues,看起来像这样:

PS>$overallSalesValues
Sale Values  AA  BB
50           1   0
10           17  12
5            14  11
4            0   1
3            3   36

在上面的示例中,来自 $AASalesValues 的值列在 AA 列下,来自 $BBSalesValues 的值列在 BB 列下,行匹配 headers原来的两个 objects.

我确实尝试过使用哈希表,但我无法弄清楚如何从动态值创建它们并将它们格式化为我需要它们的外观。

终于到了。

$TotalList = @()
foreach($n in 3..200){
    if($AASalesValues.$n -or $BBSalesValues.$n){
        $AACount = $AASalesValues.$n
        $BBcount = $BBSalesValues.$n

        $values = [PSCustomObject]@{
            'Sale Value'= $n
            AA = $AACount
            BB = $BBcount
            }
        $TotalList += $values
        }
    }
$TotalList

产生

的输出
Sale Value AA BB
---------- -- --
         3  3 36
         4     2
         5 14 11
        10 18 12
        50  1   

只需添加一点以包含“0”值而不是 $null。

我假设 $record 包含 $AASalesValues$BBSalesValues 的数据库结果列表,而不是两者,否则您需要某种选择器以避免将一组记录与另一组计数。

SaleValue 属性 将记录分组为 :

$BBSalesValues = $record | Group-Object SaleValue -NoElement

这将为您提供 SaleValue 个值及其各自计数的列表。

PS> $BBSalesValues
Count Name
----- ----
   36 3
   12 10
   11 5
    1 4

然后您可以使用这些值更新您的 CSV 数据,如下所示:

$file = 'C:\path\to\data.csv'

# read CSV into a hashtable mapping the sale value to the complete record
# (so that we can lookup the record by sale value)
$csv = @{}
Import-Csv $file | ForEach-Object {
    $csv[$_.'Sale Values'] = $_
}

# Add records for missing sale values
$($AASalesValues; $BBSalesValues) | Select-Object -Expand Name -Unique | ForEach-Object {
    if (-not $csv.ContainsKey($_)) {
        $csv[$_] = New-Object -Type PSObject -Property @{
            'Sale Values' = $_
            'AA'          = 0
            'BB'          = 0
        }
    }
}

# update records with values from $AASalesValues
$AASalesValues | ForEach-Object {
    [int]$csv[$_.Name].AA += $_.Count
}

# update records with values from $BBSalesValues
$BBSalesValues | ForEach-Object {
    [int]$csv[$_.Name].BB += $_.Count
}

# write updated records back to file
$csv.Values | Export-Csv $file -NoType

即使您更新了问题,方法也几乎相同,您只需添加另一个级别的分组来收集销售数字:

$sales = @{}
$record | Group-Object {$_.list_name.Split()[0]} | ForEach-Object {
    $sales[$_.Name] = $_.Group | Group-Object SaleValue -NoElement
}

然后将合并调整为如下所示:

$file = 'C:\path\to\data.csv'

# read CSV into a hashtable mapping the sale value to the complete record
# (so that we can lookup the record by sale value)
$csv = @{}
Import-Csv $file | ForEach-Object {
    $csv[$_.'Sale Values'] = $_
}

# Add records for missing sale values
$sales.Values | Select-Object -Expand Name -Unique | ForEach-Object {
    if (-not $csv.ContainsKey($_)) {
        $prop = @{'Sale Values' = $_}
        $sales.Keys | ForEach-Object {
            $prop[$_] = 0
        }
        $csv[$_] = New-Object -Type PSObject -Property $prop
    }
}

# update records with values from $sales
$sales.GetEnumerator() | ForEach-Object {
    $name = $_.Key
    $_.Value | ForEach-Object {
        [int]$csv[$_.Name].$name += $_.Count
    }
}

# write updated records back to file
$csv.Values | Export-Csv $file -NoType