KQL - Make the datasource variable - azure-data-explorer

i have 2 datasources which i want to be variable based on condition. But i cannot call them using variables. im not sure how can i make this work
let T1 = TableMetric;
let T2 = TableImperial;
let T3 = othertable;
let tablemetrics = case(#uommetrics=="meter",T1,#uommetrics=="imperial",T2,T3);
tablemetrics
Semantic error: '' operator: Failed to resolve scalar expression named
'T1'. Query: 'let T1 = TableMetric; let T2 = TableImperial; let T3 =
othertable; let tablemetrics =
case('a'=="meter",T1,'a'=="imperial",T2,T3); tablemetrics

This logic can be implemented with union operator
.set TableMetric <| datatable(i:int)[1,2,3]
.set TableImperial <| datatable(i:int)[4,5,6]
.set othertable <| datatable(i:int)[7,8,9]
let uommetrics = "xxx";
union
(TableMetric | where uommetrics == "meter")
,(TableImperial | where uommetrics == "imperial")
,(othertable | where uommetrics !in ("meter", "imperial"))
i
7
8
9

Related

Kusto equivalent of SQL NOT IN

I am trying to identify what records exist in table 1 that are not in table 2 (so essentially using NOT IN)
let outliers =
Table 2
| project UniqueEventGuid;
Table 1
|where UniqueEventGuid !in (outliers)
|project UniqueEventGuid
but getting 0 records back even though I know there are orphans in table 1.
Is the !in not the right syntax?
Thanks in advance!
!in operator
"In tabular expressions, the first column of the result set is
selected."
In the following example I intentionally ordered the column such that the query will result in error due to mismatched data types.
In your case, the data types might match, so the query is valid, but the results are wrong.
let t1 = datatable(i:int, x:string)[1,"A", 2,"B", 3,"C" ,4,"D" ,5,"E"];
let t2 = datatable(y:string, i:int)["d",4 ,"e",5 ,"f",6 ,"g",7];
t1
| where i !in (t2)
Relop semantic error: SEM0025: One of the values provided to the
'!in' operator does not match the left side expression type 'int',
consider using explicit cast
Fiddle
If that is indeed the case, you can reorder the columns or project only the relevant one.
Note the use of double brackets.
let t1 = datatable(i:int, x:string)[1,"A", 2,"B", 3,"C" ,4,"D" ,5,"E"];
let t2 = datatable(y:string, i:int)["d",4 ,"e",5 ,"f",6 ,"g",7];
t1
| where i !in ((t2 | project i))
i
x
1
A
2
B
3
C
Fiddle
Another option is to use leftanti join
let t1 = datatable(i:int, x:string)[1,"A", 2,"B", 3,"C" ,4,"D" ,5,"E"];
let t2 = datatable(y:string, i:int)["d",4 ,"e",5 ,"f",6 ,"g",7];
t1
| join kind=leftanti t2 on i
i
x
2
B
3
C
1
A
Fiddle

Kusto, Performing operations based on a condition

I am trying to write a Kusto query, where I have a bool variable and based on that variable I want to call different functions.
For example:
let flag = true;
let result = iff(flag == "true", function1, function2)
// function1 will return a different table and function2 will return another table.
The above code is not possible because the methods like iff() and case() can only be operated on scalar values.
So, Is there any way that I could achieve this ?
the common technique is using a union:
union (function1 | where flag), (function2 | where not(flag))
Here is a full example:
let A = datatable(col1:string)["A"];
let B = datatable(col1:string)["B"];
let funcA = view(){
A
};
let funcB= view(){
B
};
let flag = true;
union (funcA() | where flag), (funcB() | where not(flag))
col1
A
And when the flag is false:
let A = datatable(col1:string)["A"];
let B = datatable(col1:string)["B"];
let funcA = view(){
A
};
let funcB= view(){
B
};
let flag = false;
union (funcA() | where flag), (funcB() | where not(flag))
col1
B

Kusto Query Dynamic sort Order

I have started working on Azure Data Explorer( Kusto) recently.
My requirement to make sorting order of Kusto table in dynamic way.
// Variable declaration
let SortColumn ="run_date";
let OrderBy="desc";
// Actual Code
tblOleMeasurments
| take 10
|distinct column1,column2,column3,run_date
|order by SortColumn OrderBy
Here My code working fine till Sortcolumn but when I tried to add [OrderBy] after [SortColumn] kusto gives me error .
My requirement here is to pass Asc/desc value from Variable [OrderBy].
Kindly assist here with workarounds and solutions which help me .
The sort column and order cannot be an expression, it must be a literal ("asc" or "desc"). If you want to pass the sort column and sort order as a variable, create a union instead where the filter on the variables results with the desired outcome. Here is an example:
let OrderBy = "desc";
let sortColumn = "run_date";
let Query = tblOleMeasurments | take 10 |distinct column1,column2,column3,run_date;
union
(Query | where OrderBy == "desc" and sortColumn == "run_date" | order by run_date desc),
(Query | where OrderBy == "asc" and sortColumn == "run_date" | order by run_date asc)
The number of union legs would be the product of the number of candidate sort columns times two (the two sort order options).
An alternative would be sorting by a calculated column, which is based on your sort_order and sort_column. The example below works for numeric columns
let T = range x from 1 to 5 step 1 | extend y = -10 * x;
let sort_order = "asc";
let sort_column = "y";
T
| order by column_ifexists(sort_column, "") * case(sort_order == "asc", -1, 1)

Kusto: How to convert table value to scalar and return from user defined function

I have the following user-defined functions with the intention of using a case conditional to output a table of 0s or 1s saying whether or not an account is active.
case needs scalar values as it's arguments, ie pro_account_active(account) and basic_account_active(account) need to be scalar values.
I'm struggling to get around the limitation of toscalar:
User-defined functions can't pass into toscalar() invocation
information that depends on the row-context in which the function is
called.
I think if there was a function I can use in place of the "??????" that would convert active to a scalar and return it from the function it would work.
Any help greatly appreciated
let basic_account_active=(account:string) {
basic_check_1(account) // returns 0 or 1 row only
| union basic_check_2(account)
| summarize result_count = count()
| extend active = iff(result_count == 2, 1, 0)
| ??????
};
let pro_account_active=(account:string) {
pro_check_1(account) // returns 0 or 1 row only
| union pro_check_2(account)
| summarize result_count = count()
| extend active = iff(result_count == 2, 1, 0)
| ??????
};
let is_active=(account_type:string, account:string) {
case(
account_type == 'pro', pro_account_active(account),
account_type == 'basic', basic_account_active(account),
-1
)
};
datatable(account_type:string, account:string)
[
'pro', '89e5678a92',
'basic', '9d8263da45',
'pro', '0b975f2454a',
'basic', '112a3f4753',
]
| extend result = is_active(account_type, account)
You can convert the output of a query to a scalar by using the toscalar() function, i.e.
let basic_account_active=(account:string) {
toscalar(basic_check_1(account) // returns 0 or 1 row only
| union basic_check_2(account)
| summarize result_count = count()
| extend active = iff(result_count == 2, 1, 0))};
From your example it looks that you have two tables per each account type and if both have entrees for a specific account, then the account is considered active. Is that correct? If so, I would use the "join" operator to find all the entrees in the applicable tables and count them. Here is an example of one way to do it (there are other ways as well).
let basicAccounts1 = datatable(account_type:string, account:string)[ 'basic', '9d8263da45', 'basic', '111111'];
let basicAccounts2 = datatable(account_type:string, account:string)[ 'basic', '9d8263da45', 'basic', '222222'];
let proAccounts1 = datatable(account_type:string, account:string)[ 'pro', '89e5678a92', 'pro', '111111'];
let proAccounts2 = datatable(account_type:string, account:string)[ 'pro', '89e5678a92', 'pro', '222222'];
let AllAccounts = union basicAccounts1, basicAccounts2, proAccounts1, proAccounts2
| summarize count() by account, account_type;
datatable(account_type:string, account:string)
[
'pro', '89e5678a92',
'basic', '9d8263da45',
'pro', '0b975f2454a',
'basic', '112a3f4753',
]
| join kind=leftouter hint.strategy=broadcast (AllAccounts) on account, account_type
| extend IsActive = count_ >=2
| project-away count_, account1, account_type1
The results are:

kusto database as string - issues in query

I m getting database name from let statement (dbname) , the issue im getting blank output ,but when I pass the db name [when I give as hardcoded value, the query is working] . please help me to understand what the issue in query.
let view=datatable(Property:string,Value:dynamic)[];
let viewFile=datatable(FileName:string)[];
let dbnameview=datatable(dbname:string)[];
alias database db = cluster(X).database('');
let dbname=tostring(toscalar((
union isfuzzy=true dbnameview, cluster(X).database('$systemdb').Operations
| where Operation == "DatabaseCreate" and Database contains "oci-"| where State =='Completed'
and StartedOn between (datetime(2020-04-09) .. 1d)
| distinct Database , StartedOn
| order by StartedOn desc
| take 1 )));
//let dbname= 'Y';
let latestInfoFile = toscalar((
union isfuzzy=true viewFile,cluster(X).database(dbname).['TextFileLogs']
| where FileName contains "AzureStackStampInformation"
| distinct FileName
| order by FileName
| take 1)) ;
union isfuzzy=true view,(
cluster(X).database(dbname).['TextFileLogs']
| where FileName == latestInfoFile
| distinct LineNumber,FileLineContent
| order by LineNumber asc
| summarize StampInfo=(toobject(strcat_array(makelist(FileLineContent,100000), "\r\n")))
| mvexpand bagexpansion=array StampInfo
| project Property=tostring(StampInfo[0]), Value=StampInfo[1]
)|where Property contains "StampVersion" | project BuildNumber = Value;
what you're attempting to do isn't supported, as mentioned in the docs: https://learn.microsoft.com/en-us/azure/kusto/query/databasefunction

Resources