Skip to content

Commit eabac34

Browse files
committed
feat: provide support for groupby
Signed-off-by: Muhammad Aaqil <aaqilcs102@gmail.com>
1 parent 012c2de commit eabac34

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

lib/sql.js

+48-1
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,15 @@ SQLConnector.prototype.buildFields = function(model, data, excludeIds) {
12601260
return this._buildFieldsForKeys(model, data, keys, excludeIds);
12611261
};
12621262

1263+
/**
1264+
* Build a part of query for group by
1265+
* @param {String[]} groupBy Array of column names to be grouped by
1266+
* @returns a part of query for group by as a string
1267+
*/
1268+
SQLConnector.prototype.buildGroupBy = function(groupBy) {
1269+
return 'GROUP BY ' + groupBy.join(',');
1270+
};
1271+
12631272
/**
12641273
* Build an array of fields for the database operation from data array
12651274
* @param {String} model Model name
@@ -1439,7 +1448,25 @@ SQLConnector.prototype.buildSelect = function(model, filter, options) {
14391448
}
14401449
}
14411450

1451+
let extraSelect = '';
1452+
if (filter.sum) {
1453+
extraSelect = `SUM(${filter.sum}) as sumOf${filter.sum}, `;
1454+
}
1455+
if (filter.count) {
1456+
extraSelect += `COUNT(${filter.count}) as countOf${filter.count}, `;
1457+
}
1458+
if (filter.avg) {
1459+
extraSelect += `AVG(${filter.avg}) as avgOf${filter.avg}, `;
1460+
}
1461+
if (filter.min) {
1462+
extraSelect += `MIN(${filter.min}) as minOf${filter.min}, `;
1463+
}
1464+
if (filter.max) {
1465+
extraSelect += `MAX(${filter.max}) as maxOf${filter.max}, `;
1466+
}
1467+
14421468
let selectStmt = new ParameterizedSQL('SELECT ' +
1469+
extraSelect +
14431470
this.buildColumnNames(model, filter) +
14441471
' FROM ' + this.tableEscaped(model));
14451472

@@ -1449,6 +1476,10 @@ SQLConnector.prototype.buildSelect = function(model, filter, options) {
14491476
selectStmt.merge(whereStmt);
14501477
}
14511478

1479+
if (filter.groupBy) {
1480+
selectStmt.merge(this.buildGroupBy(filter.groupBy));
1481+
}
1482+
14521483
if (filter.order) {
14531484
selectStmt.merge(this.buildOrderBy(model, filter.order));
14541485
}
@@ -1510,7 +1541,23 @@ SQLConnector.prototype.all = function find(model, filter, options, cb) {
15101541
}
15111542

15121543
const objs = data.map(function(obj) {
1513-
return self.fromRow(model, obj);
1544+
const object = self.fromRow(model, obj);
1545+
if (obj[`sumOf${filter.sum}`]) {
1546+
object[`sumOf${filter.sum}`] = obj[`sumOf${filter.sum}`];
1547+
}
1548+
if (obj[`countOf${filter.count}`]) {
1549+
object[`countOf${filter.count}`] = obj[`countOf${filter.count}`];
1550+
}
1551+
if (obj[`avgOf${filter.avg}`]) {
1552+
object[`avgOf${filter.avg}`] = obj[`avgOf${filter.avg}`];
1553+
}
1554+
if (obj[`minOf${filter.min}`]) {
1555+
object[`minOf${filter.min}`] = obj[`minOf${filter.min}`];
1556+
}
1557+
if (obj[`maxOf${filter.max}`]) {
1558+
object[`maxOf${filter.max}`] = obj[`maxOf${filter.max}`];
1559+
}
1560+
return object;
15141561
});
15151562
if (filter && filter.include) {
15161563
self.getModelDefinition(model).model.include(

test/sql.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ describe('sql connector', function() {
256256
expect(orderBy).to.eql('ORDER BY `NAME`');
257257
});
258258

259+
it('builds group by with one field', function() {
260+
const groupBy = connector.buildGroupBy(['id']);
261+
expect(groupBy).to.eql('GROUP BY id');
262+
});
263+
259264
it('builds order by with two fields', function() {
260265
const orderBy = connector.buildOrderBy('customer', ['name', 'vip']);
261266
expect(orderBy).to.eql('ORDER BY `NAME`,`VIP`');
@@ -366,6 +371,28 @@ describe('sql connector', function() {
366371
});
367372
});
368373

374+
it('builds SELECT with groupBy, sum, avg, min, max & count', function() {
375+
const sql = connector.buildSelect('customer',
376+
{
377+
groupBy: ['name'],
378+
sum: 'salary',
379+
avg: 'salary',
380+
min: 'salary',
381+
max: 'salary',
382+
count: 'salary',
383+
});
384+
expect(sql.toJSON()).to.eql({
385+
sql: 'SELECT SUM(salary) as sumOfsalary, COUNT(salary) as countOfsalary,' +
386+
' AVG(salary) as avgOfsalary, MIN(salary) as minOfsalary,' +
387+
' MAX(salary) as maxOfsalary, `NAME`,`middle_name`,`LASTNAME`,`VIP`,' +
388+
'`primary_address`,`TOKEN`,`ADDRESS`' +
389+
' FROM `CUSTOMER`' +
390+
' GROUP BY name' +
391+
' ORDER BY `NAME`',
392+
params: [],
393+
});
394+
});
395+
369396
it('builds INSERT', function() {
370397
const sql = connector.buildInsert('customer', {name: 'John', vip: true});
371398
expect(sql.toJSON()).to.eql({

0 commit comments

Comments
 (0)