Join inventory with ownership records
Enrich an inventory while retaining systems whose ownership data is incomplete.
Choose a stable join key
Your inventory knows what exists; the ownership export knows which team to contact. Join them on AssetId, not on the order of rows or a computer name that could have changed. This fixture guarantees unique asset IDs in each input.
Filter the inventory to active servers first, then look up an owner for each one. This is a left-side enrichment: the inventory defines the rows in your report. An orphaned ownership entry must not create a new server, and a server without an ownership match must remain visible.
Import-Csv '/home/user/owners.csv' | Select-Object AssetId, Team
Make gaps actionable
Use Unassigned and an empty contact string when the owner export lacks a matching record. In this report, Unassigned means “no matching ownership record was supplied.” It does not prove the server has no responsible team in the real organisation.
With a small dataset, filtering the owner collection for each server is easy to follow. For larger exports, a hashtable keyed by AssetId avoids repeating that search. Both approaches are valid; keep the same report contract.
Do not send messages or update an asset system from this exercise. The contact addresses are fictional data. The result is a review list that someone can reconcile with the organisation's actual ownership process.
Import-Csv '/home/user/owners.csv' | Select-Object AssetId, Team, Contact
Put it into practice.
Emit AssetId, Name, Team, and Contact for each active server in servers.csv. Join owners.csv using AssetId. Preserve unmatched servers with Team Unassigned and Contact an empty string. Ignore ownership entries that have no active server.
See an explained solution
$owners = @(Import-Csv '/home/user/owners.csv')
foreach ($server in Import-Csv '/home/user/servers.csv' | Where-Object { $_.Kind -eq 'Server' -and $_.State -eq 'Active' }) {
$owner = $owners | Where-Object AssetId -EQ $server.AssetId
[pscustomobject]@{ AssetId=$server.AssetId; Name=$server.Name; Team=$(if ($owner) { $owner.Team } else { 'Unassigned' }); Contact=$(if ($owner) { $owner.Contact } else { '' }) }
}
The inventory remains the source of report membership. A missing match becomes a visible reconciliation task instead of removing the server from view.