NQL Syntax Cheat Sheet
Note
Ultra-quick reference for writing NQL queries - print this or keep it open while querying!
Basic Query Structure
<table> during past <time> | where <filter> | compute <calc> | summarize <agg> | list <fields> | sort <field> asc/desc | limit <n>
Clause Order (Memorize This!)
1. where (filter early!)
2. with/include (join events)
3. compute (per-object calc)
4. summarize (aggregate)
5. list (select fields)
6. sort (order results)
7. limit (restrict rows)
Comments
/* This is a comment */
/* Multi-line comments
are supported */
/* ⚠️ Comments do NOT work within clauses */
/* ✅ CORRECT - Comment between clauses */
devices
/* Filter to Windows devices */
| where operating_system.platform == windows
| list device.name
/* ❌ WRONG - Comment within clause (will error!) */
| where /* filter */ operating_system.platform == windows
Time Windows
during past 1d # 1 day (low-resolution, cloud timezone)
during past 7d # 7 days (daily aggregation)
during past 24h # 24 hours (high-resolution, user timezone)
during past 48h # 48 hours (5-15 min samples)
⚠️ past 2d ≠ past 48h (different resolution & timezone!)
Essential Keywords
| Keyword | Purpose | Example |
|---|---|---|
list | Select fields to display | list device.name, memory |
where | Filter rows | where os.name = "Windows 11" |
with | Join - objects WITH events only | with execution.crashes |
include | Join - ALL objects (even without events) | include execution.events |
compute | Calculate per object (after with/include) | compute avg = memory.avg() |
summarize | Aggregate to single result or groups | summarize total = count() |
by | Group by dimension or time | by device.name or by 1d |
sort | Order results | sort memory desc |
limit | Restrict number of rows | limit 20 |
Common Aggregation Functions
count() # Count events (avoid on sampled events!)
device.count() # Count unique devices (use this!)
user.count() # Count unique users
application.count() # Count unique applications
field.sum() # Total
field.avg() # Average (use this for computed averages!)
field.max() # Maximum
field.min() # Minimum
field.last() # Most recent value
Wildcards in Filters
where name = "Microsoft*" # Starts with Microsoft
where name = "*Office*" # Contains Office
where name = "*.exe" # Ends with .exe
where os.name = "Windows 1?" # Single char wildcard (10, 11)
Operators
== or = # Equals (both work)
!= # Not equals
> # Greater than (numbers, dates, durations)
< # Less than
>= # Greater or equal
<= # Less or equal
in [ ] # In list: where name in ["chrome.exe", "firefox.exe"]
and # Logical AND
or # Logical OR
not # Logical NOT
Output Formatting (as function)
value.as(format = percent) # 0.47 → 47%
value.as(format = currency, code = USD) # 2000 → $2,000
value.as(format = bytes) # 1073741824 → 1 GB
value.as(format = bitrate) # 1500000 → 1.5 Mbps
value.as(format = energy) # 1500 → 1.5 kWh
Critical Syntax Rules (Avoid These Errors!)
/* ❌ compute after summarize */
summarize total = sum() | compute percent = total / 100 # ERROR!
/* ✅ summarize percent = sum() / 100 # Correct */
/* ❌ Reference variables within same summarize */
summarize a = sum(), b = a / 100 # ERROR!
/* ✅ summarize a = sum(), b = sum() / 100 # Correct - repeat calculation */
/* ❌ count() on sampled events */
execution.events | summarize total = count() # Returns sample count!
/* ✅ execution.events | summarize total = device.count() # Useful! */
/* ❌ Missing time window on events */
execution.events | summarize count = count() # ERROR!
/* ✅ execution.events during past 7d | summarize count = count() # Correct */
/* ❌ Exceeding retention limits */
execution.events during past 15d # May fail (8-day high-res limit)!
/* ✅ execution.events during past 7d # Within limits */
Common Tables
devices # Device inventory (no time needed)
execution.events # Process execution (8d high-res, 30d low-res)
execution.crashes # Application crashes
device_performance.events # CPU, memory, disk metrics
connection.events # Network connections (8d high-res, 30d low-res)
web.events # Web browsing
Quick Syntax Check Before Running
□ Event table has "during past Xd" or "during past Xh"
□ Filters use correct operators (= for strings, > for numbers)
□ No compute after summarize
□ No variable references within same summarize
□ Field names match table (check Field Reference if unsure)
□ Using device.count() not count() on sampled events
□ Added | limit 10 for testing
Typical Query Patterns (Copy & Modify)
Pattern 1: Top N Devices by Metric
/* Find top 20 devices by metric */
execution.events during past 7d
| where binary.name = "PROCESS.exe"
| summarize metric = field.avg() by device.name
| list device.name, metric
| sort metric desc
| limit 20
Pattern 2: Trend Over Time
/* Hourly trend analysis */
execution.events during past 7d
| where binary.name = "PROCESS.exe"
| summarize metric = field.avg() by 1h
| sort start_time asc
Pattern 3: All Devices with Computed Metric
/* Complete device inventory with metrics */
devices
| include execution.events during past 7d
| compute metric = field.sum()
| list device.name, metric
| sort metric desc
Pattern 4: Filter and Count
devices
| with execution.crashes during past 7d
| where binary.name = "app.exe"
| summarize crash_count = count()
Pattern 5: Percentage Calculation
devices
| include execution.crashes during past 7d
| compute has_crash = count()
| summarize
total_devices = count(),
devices_with_crashes = has_crash.countif(has_crash > 0),
crash_percentage = (has_crash.countif(has_crash > 0) * 100.0) / count()
with vs include Quick Reference
/* with - Only objects WITH events (filters) */
devices
| with execution.crashes during past 7d
| list device.name
/* Returns: 15 devices (only those with crashes) */
/* include - ALL objects with metrics (computes) */
devices
| include execution.crashes during past 7d
| compute crash_count = count()
| list device.name, crash_count
/* Returns: 142 devices (all devices, crash_count = 0 for some) */
Rule: - Use with to filter (only objects with events) - Use include to compute metrics (all objects, including 0)
Common Field Patterns
Device Fields
device.name
device.operating_system.name
device.hardware.memory
device.volumes.size
device.department
Event Context Fields (Historical)
context.os_name # OS at event time
context.device_platform
context.hardware_model
context.department
execution.events Fields
binary.name # Process name
binary.real_binary.version
cpu_time # CPU usage
real_memory # Memory consumption
execution_duration
startup_duration
connection.events Fields
event.destination.domain
event.number_of_connections
event.failed_connection_ratio
incoming_traffic
outgoing_traffic
connection_establishment_time # RTT
Data Retention Quick Reference
| Table | High-Res (past Xh) | Low-Res (past Xd) |
|---|---|---|
| execution.events | 8 days | 30 days |
| connection.events | 8 days | 30 days |
| Other event tables | 30 days | 30 days |
| devices | N/A (no time needed) | N/A |
Pro Tips
Always add
| limit 10during query development, remove when finalized!Filter early with
where- massive performance gains!Use
past Xdfor trends/reports,past Xhfor troubleshooting!Test incrementally: base table → filter → aggregation → calculations
When in doubt, check Field Reference for valid fields
Related Topics
- NQL Basics - Full introduction to NQL
- Common Error Messages - Troubleshooting guide
- Query Performance Guide - Optimization techniques
- Common Query Templates - Fill-in-the-blank templates
Print this page or bookmark it for quick reference while writing queries!