Try AMQL
One model, one dataset, one query. Enough to see how AML and AQL fit together, and a playground to run it in.
AMQL has two halves. AML describes your data: which tables exist, what their columns mean, how they relate. AQL asks questions of that description. This page walks through the smallest useful example of each, on an e-commerce schema with products and categories.
You don't need to install anything. Every snippet below runs in the AMQL playground. For guided exercises with instant feedback, there is also AMQL Learn.
1. Model a table
A Model wraps one table and names its columns as dimensions. The @sql body of each dimension is the column expression; {{ #SOURCE }} stands for the table.
Model products {
type: 'table'
label: 'Products'
data_source_name: 'demodb'
table_name: 'demo.products'
dimension id {
label: 'ID'
type: 'number'
definition: @sql {{ #SOURCE.id }};;
}
dimension name {
label: 'Name'
type: 'text'
definition: @sql {{ #SOURCE.name }};;
}
dimension category_id {
label: 'Category ID'
type: 'number'
definition: @sql {{ #SOURCE.category_id }};;
}
}That is the whole modeling step for one table. The types are checked: a number dimension cannot be compared to a text one, and a typo in a dimension name is an error at authoring time, not a wrong number later.
2. Group models into a dataset
A Dataset says which models belong together and how they join. Here products and categories join through category_id.
Dataset ecommerce {
label: 'Ecommerce'
data_source_name: 'demodb'
models: [products, categories]
relationships: [
relationship(products.category_id > categories.id, true)
]
}The > reads as "many to one": many products point at one category. From here on, any query can reach categories.name from a product without writing the join.
3. Ask a question
AQL reads left to right. Start from a model, pipe it through steps. This counts products per category:
products | group(products.category_id) | select(products.category_id, count(products.id)) | products->category_id | count_products->id |
|---|---|
| 25 | 28 |
| 4 | 18 |
| 21 | 16 |
| 14 | 21 |
| 3 | 14 |
| 17 | 21 |
| 22 | 23 |
| 20 | 18 |
| 10 | 13 |
| 7 | 11 |
| 18 | 13 |
| 2 | 23 |
| 16 | 16 |
| 15 | 16 |
| 6 | 19 |
| 12 | 11 |
| 11 | 20 |
| 8 | 22 |
| 24 | 12 |
The Result tab is what comes back. The SQL tab is what AQL compiled it to, so you can always check the work.
4. Name it, reuse it
The moment a question is worth asking twice, give it a name. A measure is a named AQL expression on a model; it adapts to whatever it is grouped by.
Model products {
// ... dimensions as above
measure count_products {
label: 'Count Products'
type: 'number'
definition: @aql count(products.id) ;;
}
}Now products | group(products.category_id) | select(products.category_id, products.count_products) gives the same answer, and so does grouping by categories.name, or by nothing at all. The definition is written once.
Where to go next
- AQL in 30 minutes: the whole query language on one page.
- AMQL Learn: interactive lessons, one concept at a time, with exercises you run in the browser.
- AML overview: why a typed modeling language, and what else a model can hold.
- Cookbook: period comparison, cohort retention, percent of total and more, each with runnable results.