Joining data to make successful queries

By Gianni Castaldi

In the previous blog post, we have learned how to use string operators to query data. Querying data is one step but using it is the next step. So in this blog post, we will learn how to use the join operator. We will do this by comparing apples and pears.

We can use the join operator to join tables but also let statements, as long as you have two columns that have matching values and are the same data type. The join operator has 9 flavors and uses the innerunique by default.

leftsemiinneruniquerightsemi
leftantiinnerrightanti
leftouterfullouterrightouter

Although the default join flavor is the innerunique it is not always the best flavor for security purposes. It takes the key and does not look at the values behind this. To demonstrate this we will use the query below.

let Fruit = datatable(number:int, fruit:string) 
[
1, "Apple", 
1, "Pear" 
];
let Preparation = datatable(number:int, fruit:string) 
[
1, "Slices",
1, "Juice" 
];
Fruit
| join kind = innerunique Preparation on number

So the query did a loop through the number column but did not take the fruits. We can create a query to return the pear values by adding the following line.

| where fruit == "Pear"

When we want to display all combinations we will use the flavor inner.

let Fruit = datatable(number:int, fruit:string)
[
1, "Apple",
1, "Pear"
];
let Preparation = datatable(number:int, fruit:string)
[
1, "Slices",
1, "Juice"
];
Fruit
| join kind = inner Preparation on number

So the inner flavors return the values that are combinations. But what if we add another fruit which we don’t want to prepare?

let Fruit = datatable(number:int, fruit:string)
[
1, "Apple",
2, "Pear",
3, "Banana"
];
let Preparation = datatable(number:int, fruit:string)
[
1, "Slices",
1, "Juice",
2, "Juice"
];
Fruit
| join kind = leftouter Preparation on number

And we can do the opposite from the right side with rightouter.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = rightouter Preparation on number

To show all results from both sides we use the fullouter.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
4, "Banana"  
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
1, "Juice",
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = fullouter Preparation on number

After inner and outer the next flavor will be semi. We will use leftsemi and rightsemi to show all matches and only the left or right column.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
4, "Banana"  
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
1, "Juice",
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = leftsemi Preparation on number

And now for the right side.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
4, "Banana"  
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
1, "Juice",
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = rightsemi Preparation on number

We now know all flavors to show us the things we want to see. But what if we don’t want to see items? Then we use the leftanti and rightanti rules, where leftanti means only from the left side and rightanti only from the right side.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
4, "Banana"  
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
1, "Juice",
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = leftanti Preparation on number

And for the other table, we use rightanti.

let Fruit = datatable(number:int, fruit:string)  
[
1, "Apple",  
2, "Pear",
4, "Banana"  
];
let Preparation = datatable(number:int, fruit:string)  
[  
1, "Slices", 
1, "Juice",
2, "Juice",
3, "Dry"  
];
Fruit
| join kind = rightanti Preparation on number

During this blog post, we have compared apples and pears and learned the 9 flavors of join operators. We have also learned that the default innerunique flavor doesn’t always return the results we would expect. And that we can further target our joins with the where operator. In the next blog post we will use the join operator to join different alerts.

Thanks for reading and if you have any questions or ideas for a blog post let me know.

Alternative Text

By Gianni Castaldi

MVP | NinjaCat | Researching and Engineering Cyber Security @ KustoWorks

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close