* [LIQ] Extend with `group by` and `having` support Also update documentation with extensive examples and add some parser tests. Note: `make generate` JS files included. Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> * Merge `liq-add-support-for-aggregators` branch Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> * Fix link, remove `_` example Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> * Wrap example LIQ queries inside `query [[ .. ]]` and replace `sql` code block type to `lua` Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> * Example self-consistency fix Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> * Fixed some queries * Add experimental tags to LIQ aggregation/grouping --------- Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz> Co-authored-by: Zef Hemel <zef@zef.me>
182 lines
3.5 KiB
Markdown
182 lines
3.5 KiB
Markdown
#maturity/experimental
|
|
|
|
The `group by` and `having` clauses of [[Space Lua/Lua Integrated Query]] support aggregate functions for grouped analysis, following SQL-style semantics.
|
|
|
|
After `group by`, each result row contains:
|
|
|
|
- `key`: the group key (a single value or, for multi-key grouping, a table)
|
|
- `group`: a Lua table containing all items in that group
|
|
|
|
All aggregate functions (such as `count`, `sum`, `min`, `max`, `avg`, and custom aggregates) can be applied in `select` and `having` clauses. Aggregate expressions are available in both forms: with or without a variable binding in the `from` clause. The variable `_` always refers to the current item.
|
|
|
|
Field names used in `group by` are exposed as locals in `having`, `select`, and `order by`. Use `#group` to obtain the item count per group.
|
|
|
|
> **note** Note
|
|
> The `having` clause acts only on grouped output. For filtering individual items, use `where` prior to grouping.
|
|
|
|
# Examples
|
|
|
|
All queries operate on `index.tag 'page'`.
|
|
|
|
## Counting with and without binding
|
|
|
|
Grouping pages by their first tag, and computing the count and aggregate statistics:
|
|
|
|
**Without binding variable:**
|
|
|
|
```lua
|
|
query[[from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
select {
|
|
tag = key,
|
|
total = count(name),
|
|
min_size = min(size),
|
|
max_size = max(size),
|
|
avg_size = avg(size)
|
|
}]]
|
|
```
|
|
${query [[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
select {
|
|
tag = key,
|
|
total = count(name),
|
|
min_size = min(size),
|
|
max_size = max(size),
|
|
avg_size = avg(size)
|
|
}
|
|
]]}
|
|
|
|
**With binding variable:**
|
|
|
|
```lua
|
|
query[[
|
|
from
|
|
p = index.tag 'page'
|
|
group by
|
|
p.tags[1]
|
|
select {
|
|
tag = key,
|
|
total = count(p.name),
|
|
min_size = min(p.size),
|
|
max_size = max(p.size),
|
|
avg_size = avg(p.size)
|
|
}
|
|
]]
|
|
```
|
|
${query [[
|
|
from
|
|
p = index.tag 'page'
|
|
group by
|
|
p.tags[1]
|
|
select {
|
|
tag = key,
|
|
total = count(p.name),
|
|
min_size = min(p.size),
|
|
max_size = max(p.size),
|
|
avg_size = avg(p.size)
|
|
}
|
|
]]}
|
|
|
|
## Multi-key grouping and aggregate
|
|
|
|
```lua
|
|
query[[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1],
|
|
tags[2]
|
|
select {
|
|
first = key[1],
|
|
second = key[2],
|
|
count = count(name)
|
|
}
|
|
]]
|
|
```
|
|
${query [[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1],
|
|
tags[2]
|
|
select {
|
|
first = key[1],
|
|
second = key[2],
|
|
count = count(name)
|
|
}
|
|
]]}
|
|
|
|
## Group filtering with `having` and aggregates
|
|
|
|
Only groups with more than two items:
|
|
|
|
```lua
|
|
query[[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
having
|
|
count(name) > 2
|
|
select {
|
|
tag = key,
|
|
total = count(name)
|
|
}
|
|
]]
|
|
```
|
|
${query [[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
having
|
|
count(name) > 2
|
|
select {
|
|
tag = key,
|
|
total = count(name)
|
|
}
|
|
]]}
|
|
|
|
## Field access after grouping
|
|
|
|
Non-aggregated field references, such as `name` in `select`, refer to the first item in the group, matching common SQL and MySQL semantics.
|
|
|
|
```lua
|
|
query[[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
select {
|
|
tag = key,
|
|
first_page = name,
|
|
n = count(name)
|
|
}
|
|
]]
|
|
```
|
|
${query [[
|
|
from
|
|
index.tag 'page'
|
|
group by
|
|
tags[1]
|
|
select {
|
|
tag = key,
|
|
first_page = name,
|
|
n = count(name)
|
|
}
|
|
]]}
|
|
|
|
## Custom aggregators
|
|
|
|
Custom aggregator functions may be defined by the user using [[Library/Std/APIs/Aggregate|dedicated API]].
|
|
|
|
# See also
|
|
|
|
- [[Space Lua/Lua Integrated Query/Grouping]] — grouping queries without aggregation
|
|
- [[Space Lua/Lua Integrated Query]] — full LIQ language reference and listing available aggregators
|