* [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>
3.5 KiB
#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
havingclause acts only on grouped output. For filtering individual items, usewhereprior 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:
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:
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
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:
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.
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.
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