My SQLite database contains a nullable DateTime field that I have to read in PowerShell. My select query:
$colId = "myPrimaryKeyColumn"
$col1 = "myColumnName"
$select = "SELECT CAST($col1 as nvarchar(20)) FROM $table ORDER BY $colId DESC LIMIT 1"
Which returns CAST(Alive as nvarchar(20)) : 04/11/2022 17:17:15. How to get just the 04/11/2022 17:17:15 part?
I tried :
Invoke-SqliteQuery -SQLiteConnection $con -Query $select | Where-Object { $_.$col1}
Invoke-SqliteQuery -SQLiteConnection $con -Query $select -As DataRow | Where-Object { $_.$col1}
Invoke-SqliteQuery -SQLiteConnection $con -Query $select -As PSObject| Where-Object { $_.$col1}
Which prints just an empty line.
You need to use -As SingleValue (you don't need Where-Object)
Invoke-SqliteQuery -SQLiteConnection $con -Query $select -As SingleValue
Related
Is there a way to link a PS variable as a table within the Invoke-Sqlcmd?
I've tried LEFT JOIN $psvar as p on T1.ID=P.ID
I updated the script by making a DataTable from the advice of #Cpt.Whale.
# Define DataTable Columns
$tbl = New-Object system.Data.DataTable 'tbl_New'
$newcol = New-Object system.Data.DataColumn emplID,([string]); $tbl.columns.add($newcol)
$newcol = New-Object system.Data.DataColumn adGrp,([string]); $tbl.columns.add($newcol)
# Add data from Excel
$exelWkbk = '.\table.xlsx'
$excelQuery = '
SELECT F1 as emplID
,F2 as pcType
FROM [Sheet1$]
'
$queryOutput = Invoke-ExcelQuery $exelWkbk $excelQuery | Select-Object -Skip 1
$queryOutput | ForEach-Object {
$row = $tbl.NewRow()
$row.tmplID = ($_.emplID)
$row.adGrp = ($_.pcType)
$tbl.Rows.Add($row)
}
# Query SQL Data source joining Excel data
$sqlQuery = "
USE SQLDATABASE;
DECLARE #today as date = GETDATE();
SELECT emp.USER_ID
,wt.HOST
,a.pcType as DevicModel
FROM workstationTable as wt
JOIN employeeTable as emp on wt.USER_ID = emp.USER_ID
JOIN $tbl as a on emp.USER_ID = a.emplID
WHERE emp.NAME is not NULL
"
Invoke-Sqlcmd -Query $sqlQuery -ServerInstance 'dbName' |
Out-GridView
Powershell doesn't have a built-in function for doing SQL-style joins of different datasets. You can use Select-Object calculated properties for simple lookup-table type things, but I prefer using the Join-Object module built on LINQ:
# Gather both data sources into separate list variables:
$sqlData = Invoke-Sqlcmd -ServerInstance 'dbName' -Query '
USE SQLDATABASE;
DECLARE #today as date = GETDATE();
SELECT emp.USER_ID,wt.HOST
FROM workstationTable as wt
JOIN employeeTable as emp on wt.USER_ID = emp.USER_ID
WHERE emp.NAME is not NULL'
$excelData = Invoke-ExcelQuery $exelWkbk $excelQuery | Select-Object -Skip 1
# join the lists on a specific property
$joined = Join-Object -Type AllInLeft `
-Left $sqlData -LeftJoinProperty USER_ID `
-Right $excelData -RightJoinProperty EmplID
$joined | Out-GridView
Or since you're already using Excel, an SQL data connection in the file may be an option.
I am trying to aggregate some statistics from my broker. I have raw data in CSV format. Here are several strings from the CSV:
"Date";"OperationType";"InstrumentType";"Payment";"Currency"
"30.07.2021 6:00:00";"Dividend";"Stock";"3,42";"USD"
"30.07.2021 6:00:00";"Dividend";"Stock";"0,16";"USD"
"29.07.2021 13:55:15";"BrokerCommission";"Currency";"-7,32";"RUB"
"29.07.2021 13:55:14";"Buy";"Currency";"-14635,5";"RUB"
"29.07.2021 13:55:13";"PayIn";;"14642,82";"RUB"
"29.07.2021 6:00:00";"Dividend";"Stock";"1,93";"USD"
"29.07.2021 6:00:00";"Dividend";"Stock";"1107";"RUB"
"29.07.2021 6:00:00";"TaxDividend";"Stock";"-144";"RUB"
"28.07.2021 12:13:18";"BrokerCommission";"Currency";"-7,34";"RUB"
"28.07.2021 12:13:17";"Buy";"Currency";"-14683";"RUB"
"28.07.2021 12:13:17";"PayIn";;"14690,35";"RUB"
"28.07.2021 12:12:38";"BrokerCommission";"Stock";"-0,1";"USD"
"28.07.2021 12:12:37";"Buy";"Stock";"-196,71";"USD"
"28.07.2021 7:58:17";"BrokerCommission";"Currency";"-3,68";"RUB"
"28.07.2021 7:58:16";"Buy";"Currency";"-7369,75";"RUB"
"28.07.2021 7:58:15";"PayIn";;"7373,44";"RUB"
"28.07.2021 0:35:08";"BrokerCommission";"Stock";"-0,06";"USD"
"28.07.2021 0:35:07";"Buy";"Stock";"-122,23";"USD"
"28.07.2021 0:34:16";"BrokerCommission";"Stock";"-0,14";"USD"
"28.07.2021 0:34:15";"Buy";"Stock";"-278,92";"USD"
"28.07.2021 0:33:18";"BrokerCommission";"Stock";"-0,07";"USD"
"28.07.2021 0:33:17";"Buy";"Stock";"-142,76";"USD"
"28.07.2021 0:32:31";"BrokerCommission";"Stock";"-0,04";"USD"
"28.07.2021 0:32:30";"Buy";"Stock";"-84,31";"USD"
Here is the code I use for it:
#Initiate arrays
$InputArray = #()
$FinalArray = #()
$GroupedArray = #()
#Create array with source data
$InputArray = Import-CSV "path_to_csv_file\file.csv" -Delimiter ";" -Encoding UTF8 | Where-Object { $_.PSObject.Properties.Value -ne '' }
#Convert strings to appopriate data types
foreach ($Object in $InputArray){
$Object.Date = [datetime]::parse($Object.Date) | Get-Date -Format "yyyy-MM-dd"
$Object.Payment = [double]($Object.Payment -replace(',','.'))
}#foreach
#Group objects
$GroupedArray = $InputArray | Group-Object -Property "Date","Currency","OperationType" | `
Select-Object #{Name='Date' ;Expression={$_.Values[0]}}, `
#{Name='Currency' ;Expression={$_.Values[1]}}, `
#{Name='OperationType' ;Expression={$_.Values[2]}}, `
#{Name='Payment' ;Expression={($_.Group | Measure-Object 'Payment' -Sum).Sum}} | `
Group-Object Date
foreach ($Object in $GroupedArray){
$Date = $Object.Name
foreach ($Instance in $Object.Group){
if ($Instance.OperationType = "BrokerCommission" -and $Instance.Currency -eq "RUB"){
$BrokerComissionRUB = $null
$BrokerComissionRUB = $Instance.Payment
}#if
if ($Instance.OperationType = "BrokerCommission" -and $Instance.Currency -eq "USD"){
$BrokerComissionUSD = $null
$BrokerComissionUSD = $Instance.Payment
}#If
if ($Instance.OperationType = "Dividend" -and $Instance.Currency -eq "RUB"){
$DividendRUB = $null
$DividendRUB = $Instance.Payment
}#if
if ($Instance.OperationType = "Dividend" -and $Instance.Currency -eq "USD"){
$DividendUSD = $null
$DividendUSD = $Instance.Payment
}#If
if ($Instance.OperationType = "PayIn" -and $Instance.Currency -eq "RUB"){
$PayInRUB = $null
$PayInRUB = $Instance.Payment
}#if
}#foreach
$FinalArray += [PSCustomObject]#{
"Date" = $Date
"PayInRUB" = $PayInRUB
"DividendRUB" = $DividendRUB
"DividendUSD" = $DividendUSD
"BrokerComissionRUB" = $BrokerComissionRUB
"BrokerComissionUSD" = $BrokerComissionUSD
}
}#foreach
$FinalArray
The problem is that in $InputArray value of, for example $InputArrary[1].OperationType, has STRING format:
$InputArray[1].OperationType | gm
TypeName: System.String
But right after grouping objects with Group-Object, OperationType value type is changed to Boolean:
$GroupedArray[1].Group.operationtype | gm
TypeName: System.Boolean
So because of this strange type transformation the actual data is lost.
Nevertheless if I execute a part of a script before foreach cycle, the data type of OperationType is still STRING in $GroupedArray. If I run whole script, it changes to Boolean.
I have no idea why is that haapening and how can I avoid this. Could you please advice?
There's no strange transformation, You just have a typo, you need to use -eq and not =
You are actually set the $Instance.OperationType value to "BrokerCommission" and then replace it's value again with the results of $Instance.Currency -eq "RUB" which is a boolean value
Check it yourself in the console, execute this:
$Instance.OperationType = "BrokerCommission" -and $Instance.Currency -eq "RUB"
Results:
$Instance.OperationType
False
How am I able to append some HTML tags (<td></td>) to an existing property?
I've been stuck on this one for a little while now with no luck...
$teamConfig = #(
[pscustomobject]#{
TeamName = 'Team1'
TeamEmail = 'team1#domain.tld'
}
[pscustomobject]#{
TeamName = 'Team2'
TeamEmail = 'team2#domain.tld'
}
)
$query = "select * from INCAutomation"
$results = Invoke-Sqlcmd -query $query -ServerInstance 'localhost' -Database 'AyushTest'
$teamTickets = foreach($team in $teamConfig){
# Filter tickets based on team name
$ticketIds = $results |Where-Object TeamName -eq $team.TeamName |Select -ExpandProperty TicketID
# Output a single object per team, with all ticket IDs attached
$team |Select TeamName,TeamEmail,#{Name='TicketID';Expression={$ticketIds}}
}
$teamTickets
Output:
TeamName TeamEmail TicketID
-------- --------- --------
Team1 team1#domain.tld {INC0001, INC0002, INC0003, INC0004}
Team2 team2#domain.tld {INC0005, INC0006, INC0007}
Desired output:
TeamName TeamEmail TicketID
-------- --------- --------
Team1 team1#domain.tld {<td>INC0001</td>, <td>INC0002</td>, <td>INC0003</td>, <td>INC0004</td>}
Team2 team2#domain.tld {<td>INC0005</td>, <td>INC0006</td>, <td>INC0007</td>}
Thanks in advance!
I think you should run them through a loop and modify each string to add the desired text. You can do that and add the modified strings to a new object, which you can use to replace the original $ticketIds variable as the Expression in your output.
Here's an example of your code, modified:
$teamConfig = #(
[pscustomobject]#{
TeamName = 'Team1'
TeamEmail = 'team1#domain.tld'
}
[pscustomobject]#{
TeamName = 'Team2'
TeamEmail = 'team2#domain.tld'
}
)
$query = "select * from INCAutomation"
$results = Invoke-Sqlcmd -query $query -ServerInstance 'localhost' -Database 'AyushTest'
$teamTickets = foreach($team in $teamConfig){
# Filter tickets based on team name
$ticketIds = $results |Where-Object TeamName -eq $team.TeamName |Select -ExpandProperty TicketID
# Create an empty array
$ticketIdArray = #()
foreach ($id in $ticketIds) {
# Modify the string to include the desired output
$thisId = '<td>' + "$id" + '</td>'
# Add the modified string to the empty array
$ticketIdArray += $thisId
}
# Output a single object per team, with all ticket IDs attached
$team |Select TeamName,TeamEmail,#{Name='TicketID';Expression={$ticketIdArray}}
}
$teamTickets
I am trying to get the list of documents older than X date from my collection. However my query is not working for datetime.
I have a mongo atlas cluster with multiple databases and collections. I want to lookup for a specific collection and delete the documents under that collection that are older than X date and time. I could get the list of records and apply the filter on a powershell object but when I use the query while retrieving data, no results are returning.
$connstring = "mongodb+srv://User:pwd#clus56tg-a0ov.azure.mongodb.net"
Connect-mdbc -ConnectionString $connstring
$global:Server = $Server
Write-Host "Server `$Server $($Server.Settings.Server)"
$allDatabases = ($Server.GetDatabaseNames()).Where{($_ -notmatch 'local') -and ($_ -notmatch 'admin') -and ($_ -notmatch 'config')}
$date = "9/16/2019 0:00:00 PM"
$query = New-MdbcQuery DateTime -LTE $date
#printing the query looks like this
#{ "DateTime" : { "$lte" : "9/16/2019 0:00:00 PM" } }
$settings = New-Object MongoDB.Driver.MongoCollectionSettings
$settings.GuidRepresentation = 2
foreach($dbname in $allDatabases)
{
$database = $Server.GetDatabase($dbname)
$collections = $database.GetCollection('consumerstate', $settings)
$collections.Count()
foreach($coll in $collections)
{
Write-Output("Database Name: $coll.Database.Name, Collection Name: $coll.Name")
###This code works###
$objs = Get-MdbcData -As PS -Collection $coll
$objs.Where{$_.DateTime -le '9/16/2019 0:00:00 PM'}
#or this works
Get-MdbcData(New-MdbcQuery _id -EQ c33af1-acef-4g6a-ai05-aase56d5)
########
###This does not return any results###
Get-MdbcData -As PS -Collection $coll -Query $query
#or this
Get-MdbcData -Collection $coll -Query $query
return
}
}
The record output looks like this.
Sendfeedlooppacket {LatestRequestStatusTypeId, LatestRequestStatusDate, DisplayId, CId...}
_id 9f8a7-53vva-4xdr-b45c-a34hsd22e282
TenantId 12sf3484c-e349-43a9-9951-80345sf268452
Consumer RequestService.MessageConsumers.RequestResponseConsumer
DateTime 9/19/2019 5:39:04 PM
I have gone through the tests(https://github.com/nightroman/Mdbc/blob/master/Tests/New-MdbcQuery.test.ps1)and noticed some with datetime and the interpreted query looked like this.
test { New-MdbcQuery Name -In $date } '{ "Name" : { "$in" : [ISODate("2011-11-11T00:00:00Z")] } }'
But in my case the date is not wrapped around ISODate.
What I was missing is casting the datatype in the query.
$date = "9/16/2019 0:00:00 PM"
$query = New-MdbcQuery DateTime -LTE ([datetime]$date).
I need to do the same for guid and other datatypes.
Thanks to #nightroman for his help.
Currently I am using this to show the remote sessions on our servers, but I would like to edit the resulting table to remove the column SESSIONNAME.
param([string]$Server)
query user /server:$Server
I have tried:
a regular expression
format-table -property username,id,state,idletime,logontime
Select all the other columns.
All of these result in no output.
I tried the response from the post that has been linked here as a duplicate, but I believe it is not working because I have to fully qualify the server. I'm not sure how to tweak this code to show everything besides the sessionnames column.
param([string]$Input)
$Server = $Input + ".network"
$re = '(\w+)\s+?(\S*)\s+?(\d+)\s+Disc\s+(\S+)\s+(\d+\.\d+\.\d+)'
query user /server:$Server | Where-Object { $_ -match $re } | ForEach-Object
{
New-Object -Type PSCustomObject -Property #{
'Username' = $matches[1]
'SessionID' = $matches[3]
'IdleTime' = $matches[4]
'LogonTime' = $matches[5]
}
} | Select-Object Username, IdleTime