Kusto SCAN makes me crazy - azure-data-explorer

could someone explain this!?
range i from 1 to 3 step 1
| scan with_match_id=matchId declare (s: long, n: long=0) with
(
step s1: true => s=1, n=s1.n + 1;
step s2: true => s=2, n=s2.n + 1;
)
Output
i
s
n
matchId
1
1
1
0
2
2
1
0
2
1
1
1
3
2
1
1
3
1
1
2
Why is the first row (i=1) not matched by s2?
Why is n always 1?
That SCAN Operator makes me totally crazy. With one step it's more or less understandable, but with more than one step, I don't get it...
Thanks a lot!

Steps are always executed in their definition order.
We always start with the 1st step (s1) and then move to the 2nd, the 3rs etc. (note that a step might repeat itself multiple times).
By this definition, the 1st input line might match the 1st step, however, it cannot match any other step.
2.
n is always 1 because each step is matched only once.
In step s1 you are refering to s1.n.
s1.n is the previous value of s1.
It has a value only if you execute this step multiple time.
Since you don't, the value take is the default value you have defined when you declared n, which is 0 (n: long=0).
Same thing for step s2.

Related

Does Kusto support DEFAULT values for columns?

I have a table with 3 columns :
ID
productId
customerId
1
5
1
2
4
1
3
5
1
4
4
1
I want to add a new column called ID_MOD and its value by default will be ID%X (X is a number).
Expected result for X=3 :
ID
productId
customerId
ID_MOD
1
5
1
1
2
4
1
2
3
5
1
0
4
4
1
1
I have X instances of my app and I want each instance to query specific ID_MOD values(0/1/2.../X-1).
Is it possible to use default values for columns? If it is, can the default value be calculated based on other columns ?
what you can do is create a stored function that receives x as an input parameter, and extends your table with a calculated column (at query time).
For example:
.create-or-alter function FunctionName(x:int)
{
TableName
| extend ID_MOD = ID % x
}
If you decide x always has the same value and shouldn't be parameter, you can name the function using the same name as the table, and it will 'hide' the original table.
If the logic of calculating the extended column is well-defined in advance, you can invoke it at ingestion time, using an update policy

SQLite ORDER: Distribute result around center

Is it possible to order a SQLite select result in way that highest value is in the center and lower value are distributed around center till start and end of result set?
data set:
5
3
2
1
1
1
1
desired result:
1
1
3
5
2
1
1
Use ROW_NUMBER() window function to assign a row number to each value and with MAX() window function get the difference of each value from the max value of the table so they can be distributed around the max value:
SELECT *
FROM tablename
ORDER BY CASE WHEN ROW_NUMBER() OVER (ORDER BY col) % 2 = 1 THEN -1 ELSE 1 END *
(MAX(col) OVER () - col)
Change col to the column's name.
See the demo.

Count in xquery

I'm trying to solve this question but this code give me the result without counting it. What i mean it's that i need it to be a 13 but the result its divided by rows with a value of 1.
1
1
1
1
1
1
1
1
1
1
1
1
1
This is the question and this is what i have done.
List the number of countries that have a border (element ) in a country that has a Buddhist religion (element , value "Buddhist"). The correct query has to return the value 13.
for $var in /mondial/country
let $religion:=/mondial/country[religions="Buddhist"]/data(#id)
where $var /border/#country=$religion
return data (count($var/name)
This should get you there. I changed variable names to make things a bit more readable:
let $country := mondial/country
let $buddhist := $country[religions[./text()="Buddhist"]]/#id
return count($country[.//border[#country=$buddhist]])
Output:
13
Rather than returning the count for each item as you iterate, return each selected item and assign it to a variable, then you can get a count of the items of the sequence assigned to that variable:
let $names :=
for $var in /mondial/country
let $religion:= /mondial/country[religions="Buddhist"]/data(#id)
where $var/border/#country=$religion
return $var/name
return count($names)
You could also do this in a single XPath statement:
count(/mondial/country[border/#country=/mondial/country[religions="Buddhist"]/data(#id)])

How to count the number of commas in a string?

I use teradata. No access to functions, UDFs, stored procedures
Table
id attribute
1 strength, power
2 ring, wig, puff
3 strength, ring
4 puff, wig
5 power
I need to count the number of attributes
id att_number
1 2
2 3
3 2
4 2
5 1
How can I do this?
Of course your site should install at least the oTranslate and oReplace UDFs. Then it's a simple
CHAR_LENGTH(col) - CHAR_LENGTH(OTRANSLATE(col, ',',''))
Without those functions it's a pain in the <insert your favourite body part here>. Simply try to implement a REPLACE without oREPLACE, complex SQL with a horrible performance.
In your case it's a bit easier. If the maximum number is 12 the most efficient way will be a straight:
CASE
WHEN col LIKE '%,%,%,%,%,%,%,%,%,%,%,%,%' THEN 12
WHEN col LIKE '%,%,%,%,%,%,%,%,%,%,%,%' THEN 11
WHEN col LIKE '%,%,%,%,%,%,%,%,%,%,%' THEN 10
WHEN col LIKE '%,%,%,%,%,%,%,%,%,%' THEN 9
WHEN col LIKE '%,%,%,%,%,%,%,%,%' THEN 8
WHEN col LIKE '%,%,%,%,%,%,%,%' THEN 7
WHEN col LIKE '%,%,%,%,%,%,%' THEN 6
WHEN col LIKE '%,%,%,%,%,%' THEN 5
WHEN col LIKE '%,%,%,%,%' THEN 4
WHEN col LIKE '%,%,%,%' THEN 3
WHEN col LIKE '%,%,%' THEN 2
WHEN col LIKE '%,%' THEN 1
ELSE 0
END
No need for nested CASE/POSITION/SUBSTRING.
Using only index and substring functions, you would need a nested case statement which checks for a max of 12 attributes as show below. You would need to further nest the case statement to able to count upto 12 attributes, currently it can only count to a max of 2 attributes. [note: mytext=attributes]
SELECT id, mytext
,case
when index(mytext, ',')= 0 then 0
when index(mytext, ',')>0 then
case
when index(substring(mytext, index(mytext, ','), length(mytext)), ',')=0 then 1
when index(substring(mytext, index(mytext, ','), length(mytext)), ',')>0 then 2
end
end
from mydb.sd_test
order by id;
SELECT colname
,CHARACTERS(TRIM(colname)) -CHARACTERS(TRIM(OREPLACE(colname,',',''))) +1
SAMPLE 100 FROM tablename
Can use a much simpler and efficient one liner code as below:
select length(trim(regexp_replace(Column_Name,'[^,]+','')));

generate 6 numbers between 1 and 2 in a 2:1 ratio in SQL or PL/SQL

how can i generate 6 numbers between 1 and 2 where 4 of the numbers will be 1 and the other 2 will be 2 in a random order i.e.
results
1
2
1
1
1
2
and also in a different ratio i.e. 3:2:1 for numbers between 1 and 3 for 12 numbers
i.e.
results
1
1
2
3
1
2
1
3
1
1
3
3
results don't have to be in this order but in the ratios as above in oracle SQL or PL/SQL
To get the ratios perfect you could do something like this - generate all the numbers, then sort in random order:
SELECT r
FROM (SELECT CASE
WHEN ROWNUM <=4 THEN 1
ELSE 2
END AS r
FROM DUAL
CONNECT BY LEVEL <= 6)
ORDER BY DBMS_RANDOM.value;
R
----------------------
2
1
1
2
1
1
I think this will work in straight SQL; it's horrifically inefficient, and a PL/SQL one might be less so. It's also completely static; differing ratios call for a different number of values selected.
select value
from (
select mod(value, 2) + 1 as value,
row_number() over (partition by
case mod(value, 2) = 1
then 1
else 0
end) as twos_row,
row_number() over (partition by
case mod(value, 2) = 0
then 1
else 0
end) as ones_row
from (select dbms_crypto.randominteger as value
from dba_objects
order by object_id
)
)
where twos_rows <= 2
or ones_rows <= 4
The inner-most select grabs a big stack of random numbers. The next query out determines whether that random value would be a 2 or a 1 by mod'ing the earlier random value. The last level of nesting just filters out all the rows after the correct number of that type of row has been returned.
This is untested and fragile. If you need a solution that's reliable and performance, I'd recommend PL/SQL, where you
loop
pick off random numbers
determine what partition in your set of values they'd fit into
keep them if that partition hasn't been satisfied
exit when all partitions have been satisfied.

Resources