Count and group by multiple columns - powershell

I have a CSV file with the following columns:
Error_ID
Date
hh (hour in two digit)
Error description
It look like this:
In SQL it was very easy:
SELECT X,Y,Count(1)
FROM #Table
GROUP BY X,Y
In PowerShell its a bit more different.

The Group-Object cmdlet allows grouping by multiple properties:
Import-Csv 'C:\path\to\your.csv' | Group-Object ErrorID, Date
which will give you a result like this:
Count Name Group
----- ---- -----
3 1, 15/07/2016 {#{ErrorID=1; Date=15/07/2016; Hour=16}, #{ErrorID=1; Da...
1 2, 16/07/2016 {#{ErrorID=2; Date=16/07/2016; Hour=9}}
However, to display grouped values in tabular form like an SQL query would do you need to extract them from the groups with calculated properties:
Import-Csv 'C:\path\to\your.csv' | Group-Object ErrorID, Date |
Select-Object #{n='ErrorID';e={$_.Group[0].ErrorID}},
#{n='Date';e={$_.Group[0].Date}}, Count
which will produce output like this:
ErrorID Date Count
------- ---- -----
1 15/07/2016 3
2 16/07/2016 1

You can use the following:
$csv = import-csv path/to/csv.csv
$csv | group-object errorid
Count Name Group
----- ---- -----
2 1 {#{errorID=1; time=15/7/2016; description=bad}, #{errorID=1; time=15/8/2016; description=wow}}
1 3 {#{errorID=3; time=15/7/2016; description=worse}}
1 5 {#{errorID=5; time=15/8/2016; description=the worst}}
$csv | where {$_.errorid -eq "2"}
errorID time description
------- ---- -----------
1 15/7/2016 bad
1 15/8/2016 wow
You can Pipe first and second example to get the desired result.

Related

Powershell make list with object groupping

Assuming a CSV File:
Name,group_name,group_id
foo,Best,1
bar,Worst,2
baz,Best,1
bob,Worst,2
What's the simplest form of Grouping by Powershell I can use to have output like:
Count group_id group_name Names
----- -------- ---------- -----
2 1 Best ["foo", "baz"]
2 2 Worst ["bar", "bob"]
Use the Group-Object cmdlet to group the rows together by name and id, then use Select-Object to extract the appropriate details from each group as individual properties:
# replace with `$Data = Import-Csv path\to\file.csv`
$Data = #'
Name,group_name,group_id
foo,Best,1
bar,Worst,2
baz,Best,1
bob,Worst,2
'#|ConvertFrom-Csv
# Group rows, then construct output record with `Select-Object`
$Data |Group-Object group_name,group_id |Select-Object Count,#{Name='group_id';Expression={$_.Group[0].group_id}},#{Name='group_name';Expression={$_.Group[0].group_name}},#{Name='Names';Expression={$_.Group.Name}}

How to get a numbered count of different items in powershell

Im using the following powershell query to get a list of disks:
Get-NcDisk | Select-Object -Property model | Sort-Object -Property Model -Descending | foreach {$_.model}
It outputs like below:
X316_SMKRE06TA07
X316_HARIH06TA07
X316_HARIH06TA07
X316_HARIH06TA07
How can I get it to output a numbered count of each type of disk like below:
1 X316_SMKRE06TA07
3 X316_HARIH06TA07
Group-Object will do this for you..
I can't use Get-NcDisk but it may just be:
Get-NcDisk | Select-Object -ExpandProperty model | Group-Object
Example output using a string array:
"X316_SMKRE06TA07","X316_HARIH06TA07","X316_HARIH06TA07","X316_HARIH06TA07" | Group-Object
Count Name Group
----- ---- -----
1 X316_SMKRE06TA07 {X316_SMKRE06TA07}
3 X316_HARIH06TA07 {X316_HARIH06TA07, X316_HARIH06TA07, X316_HARIH06TA07}

How to get the value only from the Hashtable in PowerShell?

If I have a hastable $states = #{ 1 = 15; 2 = 5; 3 = 41 }, The result shows
Name Value
---- -----
3 41
2 5
1 15
I used $states.GetEnumerator() | sort value -Descending | select -Last 1 to find the minimum value that I need.
The result is:
Name Value
---- -----
2 5
However, I cannot use the value (5) as a new variable to do a calculation. This is due to the result cotains both name and value. Is there any method to get the minimum value only from the result?
Use the .Values property from the beginning:
$states.Values | Sort-Object -Descending | Select-Object -Last 1
Or expand the .Value property:
$states.GetEnumerator() | sort value -Descending | select -Last 1 -ExpandProperty Value

How to find duplicate values in powershell hash

Imagine the following hash:
$h=#{}
$h.Add(1,'a')
$h.Add(2,'b')
$h.Add(3,'c')
$h.Add(4,'d')
$h.Add(5,'a')
$h.Add(6,'c')
What query would return the 2 duplicate values 'a' and 'c' ?
Basically I am looking for the powershell equivalent of the following SQL query (assuming the table h(c1,c2):
select c1
from h
group by c1
having count(*) > 1
You could try this:
$h.GetEnumerator() | Group-Object Value | ? { $_.Count -gt 1 }
Count Name Group
----- ---- -----
2 c {System.Collections.DictionaryEntry, System.Collections.DictionaryEntry}
2 a {System.Collections.DictionaryEntry, System.Collections.DictionaryEntry}
If you store the results, you could dig into the group to get the key-name for the duplicate entries. Ex.
$a = $h.GetEnumerator() | Group-Object Value | ? { $_.Count -gt 1 }
#Check the first group(the one with 'c' as value)
$a[0].Group
Name Value
---- -----
6 c
3 c
You can use another hash table:
$h=#{}
$h.Add(1,'a')
$h.Add(2,'b')
$h.Add(3,'c')
$h.Add(4,'d')
$h.Add(5,'a')
$h.Add(6,'c')
$h1=#{}
$h.GetEnumerator() | foreach { $h1[$_.Value] += #($_.name) }
$h1.GetEnumerator() | where { $_.value.count -gt 1}
Name Value
---- -----
c {6, 3}
a {5, 1}
Just a slightly different question:
How to list the duplicate items of a PowerShell Array
But a similar solution as from Frode F:
$Duplicates = $Array | Group | ? {$_.Count -gt 1} | Select -ExpandProperty Name

PS: Filter selected rows with only max values as output?

I have a variable results ($result) of several rows of data or object like this:
PS> $result | ft -auto;
name value
---- -----
a 1
a 2
b 30
b 20
....
what I need to get all the rows of name and max(value) like this filtered output:
PS> $result | ? |ft -auto
name value
---- -----
a 2
b 30
....
Not sure what command or filters available (as ? in above) so that I can get each name and only the max value for the name out?
$result | group name | select name,#{n='value';e={ ($_.group | measure value -max).maximum}}
This should do the trick:
PS> $result | Foreach {$ht=#{}} `
{if ($_.Value -gt $ht[$_.name].Value) {$ht[$_.Name]=$_}} `
{$ht.Values}
This is essentially using the Begin/Process/End scriptblock parameters of the Foreach-Object cmdlet to stash input objects with a max value based on a key into a hashtable.
Note: watch out for extra spaces after the line continuation character (`) - there shouldn't be any.