Part 3: Advanced Query Operators and Functions

Moving Beyond the Basics

After mastering fundamental operators, I discovered that KQL's advanced capabilities truly shine when analyzing complex scenarios across multiple data sources. In this part, I'll share the advanced operators and functions that transformed my observability practice.

join - Combining Data from Multiple Tables

The join operator is essential when correlating data across different log sources. Unlike SQL joins, KQL joins are optimized for time-series data.

Join Types I Use

1. innerunique (default) - Most common in my queries:

// Correlate VM performance with heartbeat data
Perf
| where TimeGenerated > ago(1h)
| where CounterName == "% Processor Time"
| summarize AvgCpu = avg(CounterValue) by Computer, bin(TimeGenerated, 5m)
| join kind=innerunique (
    Heartbeat
    | where TimeGenerated > ago(1h)
    | summarize LastHeartbeat = max(TimeGenerated) by Computer
) on Computer
| project Computer, AvgCpu, LastHeartbeat

2. leftouter - When I need all left-side records:

3. rightouter - Less common but useful:

4. inner - Traditional inner join:

Real-World Join Pattern: Correlating Application and Infrastructure

This is a pattern I use frequently to correlate application errors with infrastructure issues:

Join Performance Tips from Experience

union - Combining Similar Tables

Use union when you need to query across multiple tables or workspaces.

Basic Union:

Union with Wildcards:

Cross-Workspace Queries:

Real Pattern: Unified Error Dashboard

This is how I build a unified error view across all application components:

mv-expand - Expanding Multi-Value Fields

mv-expand is crucial when working with arrays or dynamic fields. I use it frequently with Azure resource logs.

Expanding Arrays:

Real Pattern: Analyzing Tags

I use this pattern to analyze Azure resource tags:

Expanding Nested JSON:

parse - Extracting Structured Data

The parse operator extracts fields from strings using patterns.

Simple Parse:

Multiple Parse Patterns:

Real Pattern: Parsing API Gateway Logs

This is how I parse Application Gateway logs:

make-series - Time Series Analysis

make-series is powerful for creating time-series data with automatic gap filling.

Basic Time Series:

Time Series with Gap Filling:

Real Pattern: Anomaly Detection

I combine make-series with series_decompose_anomalies for anomaly detection:

let - Creating Variables and Functions

let statements make complex queries more readable and reusable.

Variable Definition:

Tabular Variables:

Functions with let:

Real Pattern: Reusable Time Windows

This is a pattern I use across many queries:

Advanced Functions

String Functions:

Array and Bag Functions:

Mathematical Functions:

Complex Real-World Query Patterns

Pattern 1: Request Success Rate with Latency Analysis

Pattern 2: Resource Health Correlation Matrix

Pattern 3: Service Dependency Analysis

Query Optimization Techniques

1. Use materialized views for repeated queries:

2. Partition by time first:

3. Use summarize instead of distinct when possible:

Key Takeaways

  • join correlates data across tables - use with filters for performance

  • union combines similar tables - great for multi-source queries

  • mv-expand handles arrays and dynamic fields effectively

  • parse extracts structured data from strings

  • make-series creates time-series with automatic gap filling

  • let improves query readability and reusability

  • Advanced functions enable sophisticated data transformation

  • Always optimize by filtering early and reducing data processed

In Part 4, we'll focus specifically on querying Azure Log Analytics workspace, understanding different log schemas, and practical patterns for common Azure resources.

Last updated