Having
The Having
type describes a function that lets you specify conditions to filter results, based on the grouped Cells resulting from a Group
clause.
Calling this function with two parameters is used to include only those Rows for which a specified Cell
in the query's root Table
has a specified value.
(
selectedOrGroupedCellId: string,
equals: Cell,
): void
Type | Description | |
---|---|---|
selectedOrGroupedCellId | string | |
equals | Cell | The value that the |
returns | void | This has no return value. |
Since
v2.0.0
Calling this function with one callback parameter is used to include only those Rows which meet a calculated boolean condition.
(condition: (getSelectedOrGroupedCell: GetCell) => boolean): void
Type | Description | |
---|---|---|
condition | (getSelectedOrGroupedCell: GetCell) => boolean | A callback that takes a |
returns | void | This has no return value. |
Since
v2.0.0
The Having
function is provided to the third query
parameter of the setQueryDefinition
method.
A Having
condition has to be true for a Row
to be included in the results. Each Having
class is additive, as though combined with a logical 'and'. If you wish to create an 'or' expression, use the single parameter version of the type that allows arbitrary programmatic conditions.
The Where
keyword differs from the Having
keyword in that the former describes conditions that should be met by underlying Cell
values (whether selected or not), and the latter describes conditions based on calculated and aggregated values - after Group
clauses have been applied.
Whilst it is technically possible to use a Having
clause even if the results have not been grouped with a Group
clause, you should expect it to be less performant than using a Where
clause, due to that being applied earlier in the query process.
Examples
This example shows a query that filters the results from a grouped Table
by comparing a Cell
from it with a value.
import {createQueries, createStore} from 'tinybase';
const store = createStore().setTable('pets', {
fido: {species: 'dog', price: 5},
felix: {species: 'cat', price: 4},
cujo: {species: 'dog', price: 4},
tom: {species: 'cat', price: 3},
carnaby: {species: 'parrot', price: 3},
polly: {species: 'parrot', price: 3},
});
const queries = createQueries(store);
queries.setQueryDefinition('query', 'pets', ({select, group, having}) => {
select('pets', 'species');
select('pets', 'price');
group('price', 'min').as('minPrice');
group('price', 'max').as('maxPrice');
having('minPrice', 3);
});
queries.forEachResultRow('query', (rowId) => {
console.log({[rowId]: queries.getResultRow('query', rowId)});
});
// -> {0: {species: 'cat', minPrice: 3, maxPrice: 4}}
// -> {1: {species: 'parrot', minPrice: 3, maxPrice: 3}}
This example shows a query that filters the results from a grouped Table
with a condition that is calculated from Cell
values.
import {createQueries, createStore} from 'tinybase';
const store = createStore().setTable('pets', {
fido: {species: 'dog', price: 5},
felix: {species: 'cat', price: 4},
cujo: {species: 'dog', price: 4},
tom: {species: 'cat', price: 3},
carnaby: {species: 'parrot', price: 3},
polly: {species: 'parrot', price: 3},
});
const queries = createQueries(store);
queries.setQueryDefinition('query', 'pets', ({select, group, having}) => {
select('pets', 'species');
select('pets', 'price');
group('price', 'min').as('minPrice');
group('price', 'max').as('maxPrice');
having(
(getSelectedOrGroupedCell) =>
getSelectedOrGroupedCell('minPrice') !=
getSelectedOrGroupedCell('maxPrice'),
);
});
queries.forEachResultRow('query', (rowId) => {
console.log({[rowId]: queries.getResultRow('query', rowId)});
});
// -> {0: {species: 'dog', minPrice: 4, maxPrice: 5}}
// -> {1: {species: 'cat', minPrice: 3, maxPrice: 4}}
// Parrots are filtered out because they have zero range in price.
Since
v2.0.0