diff --git a/public/app/plugins/datasource/postgres/partials/query.editor.html b/public/app/plugins/datasource/postgres/partials/query.editor.html
index 58d2415479a..0c053388034 100644
--- a/public/app/plugins/datasource/postgres/partials/query.editor.html
+++ b/public/app/plugins/datasource/postgres/partials/query.editor.html
@@ -66,7 +66,7 @@
-
+
@@ -83,12 +83,12 @@
+ handle-event="ctrl.handleGroupPartEvent(part, $index, $event)">
-
+
diff --git a/public/app/plugins/datasource/postgres/postgres_query.ts b/public/app/plugins/datasource/postgres/postgres_query.ts
index eb51449dd39..4cd3ddefaa2 100644
--- a/public/app/plugins/datasource/postgres/postgres_query.ts
+++ b/public/app/plugins/datasource/postgres/postgres_query.ts
@@ -134,14 +134,21 @@ export default class PostgresQuery {
let columnName = _.find(column, (g: any) => g.type === 'column');
query = columnName.params[0];
- let aggregate = _.find(column, (g: any) => g.type === 'aggregate');
+ let aggregate = _.find(column, (g: any) => g.type === 'aggregate' || g.type === 'percentile');
let special = _.find(column, (g: any) => g.type === 'window');
if (aggregate) {
- if (special) {
- query = aggregate.params[0] + '(' + query + ' ORDER BY ' + this.target.timeColumn + ')';
- } else {
- query = aggregate.params[0] + '(' + query + ')';
+ switch (aggregate.type) {
+ case 'aggregate':
+ if (special) {
+ query = aggregate.params[0] + '(' + query + ' ORDER BY ' + this.target.timeColumn + ')';
+ } else {
+ query = aggregate.params[0] + '(' + query + ')';
+ }
+ break;
+ case 'percentile':
+ query = aggregate.params[0] + '(' + aggregate.params[1] + ') WITHIN GROUP (ORDER BY ' + query + ')';
+ break;
}
}
diff --git a/public/app/plugins/datasource/postgres/query_ctrl.ts b/public/app/plugins/datasource/postgres/query_ctrl.ts
index 88ef587037d..0191d46065f 100644
--- a/public/app/plugins/datasource/postgres/query_ctrl.ts
+++ b/public/app/plugins/datasource/postgres/query_ctrl.ts
@@ -112,6 +112,14 @@ export class PostgresQueryCtrl extends QueryCtrl {
{ text: 'Variance', value: 'variance' },
],
},
+ {
+ text: 'Ordered-Set Aggregate Functions',
+ value: 'percentile',
+ submenu: [
+ { text: 'Percentile (continuous)', value: 'percentile_cont' },
+ { text: 'Percentile (discrete)', value: 'percentile_disc' },
+ ],
+ },
{
text: 'Window Functions',
value: 'window',
@@ -121,9 +129,9 @@ export class PostgresQueryCtrl extends QueryCtrl {
{ text: 'Sum', value: 'sum' },
],
},
- { text: 'Alias', value: 'alias' },
- { text: 'Column', value: 'column' },
];
+ this.selectMenu.push({ text: 'Alias', value: 'alias' });
+ this.selectMenu.push({ text: 'Column', value: 'column' });
}
toggleEditorMode() {
@@ -241,15 +249,17 @@ export class PostgresQueryCtrl extends QueryCtrl {
});
this.selectParts.push(parts);
break;
+ case 'percentile':
+ partModel.params.push('0.95');
case 'aggregate':
// add group by if no group by yet
if (this.target.group.length === 0) {
this.addGroup('time', '1m');
}
- case 'window':
- let index = _.findIndex(selectParts, (p: any) => p.def.type === item.value);
- if (index !== -1) {
- selectParts[index] = partModel;
+ let aggIndex = _.findIndex(selectParts, (p: any) => p.def.type === 'aggregate' || p.def.type === 'percentile');
+ if (aggIndex !== -1) {
+ // replace current aggregation
+ selectParts[aggIndex] = partModel;
} else {
selectParts.splice(1, 0, partModel);
}
@@ -257,6 +267,26 @@ export class PostgresQueryCtrl extends QueryCtrl {
addAlias = true;
}
break;
+ case 'window':
+ let windowIndex = _.findIndex(selectParts, (p: any) => p.def.type === 'window');
+ if (windowIndex !== -1) {
+ // replace current window function
+ selectParts[windowIndex] = partModel;
+ } else {
+ let aggIndex = _.findIndex(
+ selectParts,
+ (p: any) => p.def.type === 'aggregate' || p.def.type === 'percentile'
+ );
+ if (aggIndex !== -1) {
+ selectParts.splice(aggIndex + 1, 0, partModel);
+ } else {
+ selectParts.splice(1, 0, partModel);
+ }
+ }
+ if (!_.find(selectParts, (p: any) => p.def.type === 'alias')) {
+ addAlias = true;
+ }
+ break;
case 'alias':
addAlias = true;
break;
@@ -322,7 +352,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
}
}
- onGroupPartEvent(part, index, evt) {
+ handleGroupPartEvent(part, index, evt) {
switch (evt.name) {
case 'get-param-options': {
return this.datasource
@@ -379,7 +409,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
// remove aggregations
this.selectParts = _.map(this.selectParts, (s: any) => {
return _.filter(s, (part: any) => {
- if (part.def.type === 'aggregate') {
+ if (part.def.type === 'aggregate' || part.def.type === 'percentile') {
return false;
}
return true;
@@ -436,7 +466,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
return this.$q.when(options);
}
- whereAddAction(part, index) {
+ addWhereAction(part, index) {
switch (this.whereAdd.type) {
case 'macro': {
this.whereParts.push(sqlPart.create({ type: 'macro', name: this.whereAdd.value, params: [] }));
@@ -468,7 +498,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
.catch(this.handleQueryError.bind(this));
}
- onGroupAction() {
+ addGroupAction() {
switch (this.groupAdd.value) {
default: {
this.addGroup(this.groupAdd.type, this.groupAdd.value);
diff --git a/public/app/plugins/datasource/postgres/sql_part.ts b/public/app/plugins/datasource/postgres/sql_part.ts
index 487ddb50276..9cf0bd8f425 100644
--- a/public/app/plugins/datasource/postgres/sql_part.ts
+++ b/public/app/plugins/datasource/postgres/sql_part.ts
@@ -45,10 +45,35 @@ register({
register({
type: 'aggregate',
style: 'label',
- params: [{ name: 'name', type: 'string', dynamicLookup: true }],
+ params: [
+ {
+ name: 'name',
+ type: 'string',
+ options: ['avg', 'count', 'min', 'max', 'sum', 'stddev', 'variance'],
+ },
+ ],
defaultParams: ['avg'],
});
+register({
+ type: 'percentile',
+ label: 'Aggregate:',
+ style: 'label',
+ params: [
+ {
+ name: 'name',
+ type: 'string',
+ options: ['percentile_cont', 'percentile_disc'],
+ },
+ {
+ name: 'fraction',
+ type: 'number',
+ options: ['0.5', '0.75', '0.9', '0.95', '0.99'],
+ },
+ ],
+ defaultParams: ['percentile_cont', '0.95'],
+});
+
register({
type: 'alias',
style: 'label',