add moving average to query builder

This commit is contained in:
Sven Klemm 2018-08-03 07:44:36 +02:00
parent 0b57e88f9e
commit dabfd88cd9
3 changed files with 58 additions and 21 deletions

View File

@ -142,7 +142,7 @@ export default class PostgresQuery {
query = columnName.params[0];
let aggregate = _.find(column, (g: any) => g.type === 'aggregate' || g.type === 'percentile');
let windows = _.find(column, (g: any) => g.type === 'window');
let windows = _.find(column, (g: any) => g.type === 'window' || g.type === 'moving_window');
if (aggregate) {
let func = aggregate.params[0];
@ -174,25 +174,32 @@ export default class PostgresQuery {
let over = overParts.join(' ');
let curr: string;
let prev: string;
switch (windows.params[0]) {
case 'increase':
curr = query;
prev = 'lag(' + curr + ') OVER (' + over + ')';
query = '(CASE WHEN ' + curr + ' >= ' + prev + ' THEN ' + curr + ' - ' + prev + ' ELSE ' + curr + ' END)';
break;
case 'rate':
let timeColumn = this.target.timeColumn;
if (aggregate) {
timeColumn = 'min(' + timeColumn + ')';
}
switch (windows.type) {
case 'window':
switch (windows.params[0]) {
case 'increase':
curr = query;
prev = 'lag(' + curr + ') OVER (' + over + ')';
query = '(CASE WHEN ' + curr + ' >= ' + prev + ' THEN ' + curr + ' - ' + prev + ' ELSE ' + curr + ' END)';
break;
case 'rate':
let timeColumn = this.target.timeColumn;
if (aggregate) {
timeColumn = 'min(' + timeColumn + ')';
}
curr = query;
prev = 'lag(' + curr + ') OVER (' + over + ')';
query = '(CASE WHEN ' + curr + ' >= ' + prev + ' THEN ' + curr + ' - ' + prev + ' ELSE ' + curr + ' END)';
query += '/extract(epoch from ' + timeColumn + ' - lag(' + timeColumn + ') OVER (' + over + '))';
curr = query;
prev = 'lag(' + curr + ') OVER (' + over + ')';
query = '(CASE WHEN ' + curr + ' >= ' + prev + ' THEN ' + curr + ' - ' + prev + ' ELSE ' + curr + ' END)';
query += '/extract(epoch from ' + timeColumn + ' - lag(' + timeColumn + ') OVER (' + over + '))';
break;
default:
query = windows.params[0] + '(' + query + ') OVER (' + over + ')';
break;
}
break;
default:
query = windows.params[0] + '(' + query + ') OVER (' + over + ')';
case 'moving_window':
query = windows.params[0] + '(' + query + ') OVER (' + over + ' ROWS ' + windows.params[1] + ' PRECEDING)';
break;
}
}

View File

@ -138,6 +138,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
{ text: 'Increase', value: 'increase' },
{ text: 'Rate', value: 'rate' },
{ text: 'Sum', value: 'sum' },
{ text: 'Moving Average', value: 'avg', type: 'moving_window' },
],
};
this.selectMenu.push(windows);
@ -263,14 +264,22 @@ export class PostgresQueryCtrl extends QueryCtrl {
return _.findIndex(selectParts, (p: any) => p.def.type === 'aggregate' || p.def.type === 'percentile');
}
findWindowIndex(selectParts) {
return _.findIndex(selectParts, (p: any) => p.def.type === 'window' || p.def.type === 'moving_window');
}
addSelectPart(selectParts, item, subItem) {
let partModel = sqlPart.create({ type: item.value });
let partType = item.value;
if (subItem && subItem.type) {
partType = subItem.type;
}
let partModel = sqlPart.create({ type: partType });
if (subItem) {
partModel.params = [subItem.value];
}
let addAlias = false;
switch (item.value) {
switch (partType) {
case 'column':
let parts = _.map(selectParts, function(part: any) {
return sqlPart.create({ type: part.def.type, params: _.clone(part.params) });
@ -295,8 +304,10 @@ export class PostgresQueryCtrl extends QueryCtrl {
addAlias = true;
}
break;
case 'moving_window':
partModel.params.push('5');
case 'window':
let windowIndex = _.findIndex(selectParts, (p: any) => p.def.type === 'window');
let windowIndex = this.findWindowIndex(selectParts);
if (windowIndex !== -1) {
// replace current window function
selectParts[windowIndex] = partModel;

View File

@ -113,6 +113,25 @@ register({
defaultParams: ['increase'],
});
register({
type: 'moving_window',
style: 'label',
label: 'Moving Window:',
params: [
{
name: 'function',
type: 'string',
options: ['avg'],
},
{
name: 'window_size',
type: 'number',
options: ['3', '5', '7', '10', '20'],
},
],
defaultParams: ['avg', '5'],
});
export default {
create: createPart,
};