From 8f4550a802f2e8c2556fc360c8f548064eaf17f4 Mon Sep 17 00:00:00 2001 From: Ezekiel Keator <20361796+tastypackets@users.noreply.github.com> Date: Tue, 10 Nov 2020 20:02:45 -0600 Subject: [PATCH] Do not include null in COUNT or AVG fixes #1251 (#1252) --- src/423groupby.js | 28 +++++++++-- test/test812.js | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 test/test812.js diff --git a/src/423groupby.js b/src/423groupby.js index f2b7225ae4..360b2dbcc0 100755 --- a/src/423groupby.js +++ b/src/423groupby.js @@ -166,7 +166,15 @@ if(false) { } else { // return "'"+colas+'\':(typeof '+colexp+' != "undefined")?1:0,'; // } else { - return "'" + colas + "':(typeof " + colexp + ' != "undefined")?1:0,'; + return ( + "'" + + colas + + "':(typeof " + + colexp + + ' == "undefined" || ' + + colexp + + ' === null) ? 0 : 1,' + ); } // else if(col.aggregatorid == 'MIN') { return "'"+col.as+'\':r[\''+col.as+'\'],'; } @@ -189,7 +197,9 @@ if(false) { colas + "':(typeof " + colexp + - ' != "undefined")?1:0,' + ' == "undefined" || ' + + colexp + + ' === null) ? 0 : 1,' ); } else if (col.aggregatorid === 'AGGR') { aft += ",g['" + colas + "']=" + col.expression.toJS('g', -1); @@ -300,7 +310,17 @@ if(false) { if (col.expression.columnid === '*') { return pre + "g['" + colas + "']++;" + post; } else { - return pre + 'if(typeof ' + colexp + '!="undefined") g[\'' + colas + "']++;" + post; + return ( + pre + + 'if(typeof ' + + colexp + + '!="undefined" && ' + + colexp + + " !== null) g['" + + colas + + "']++;" + + post + ); } } else if (col.aggregatorid === 'ARRAY') { return pre + "g['" + colas + "'].push(" + colexp + ');' + post; @@ -327,7 +347,7 @@ if(false) { ')||0;' + "g['_COUNT_" + colas + - '\']+=(typeof y!="undefined")?1:0;' + + '\']+=(typeof y == "undefined" || y === null) ? 0 : 1;' + "g['" + colas + "']=g['_SUM_" + diff --git a/test/test812.js b/test/test812.js new file mode 100644 index 0000000000..8de565573a --- /dev/null +++ b/test/test812.js @@ -0,0 +1,115 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); +} else { + __dirname = '.'; +} + +describe('Test 243 AVG bug', function () { + it('1. Does not count null when using GROUP BY', function (done) { + var data = [ + {a: 1, b: 2, c: null}, + {a: 1, b: null, c: null}, + {a: null, b: null, c: null}, + {a: 1, b: undefined, c: null}, + {a: null, b: 2, c: null}, + ]; + var res = alasql( + 'SELECT COUNT(*) as all_rows, COUNT(a) as a, COUNT(b) as b, COUNT(c) as c FROM ?', + [data] + ); + assert.deepEqual(res, [ + { + all_rows: 5, + a: 3, + b: 2, + c: 0, + }, + ]); + done(); + }); + + it('2. Does not count null when using GROUP BY', function (done) { + var data = [{a: 1}, {a: 1}, {a: 2}, {a: 3}, {a: 1}, {a: 2}, {a: undefined}, {a: null}]; + var res = alasql('SELECT a, COUNT(*) as b, COUNT(a) as c FROM ? GROUP BY a', [data]); + assert.deepEqual(res, [ + {a: 1, b: 3, c: 3}, + {a: 2, b: 2, c: 2}, + {a: 3, b: 1, c: 1}, + {a: undefined, b: 1, c: 0}, + {a: null, b: 1, c: 0}, + ]); + done(); + }); + + it('3. Does not count null in AVG', function (done) { + var arr = [ + { + person: 1, + sold: 5, + }, + { + person: 2, + sold: 10, + }, + { + person: 1, + sold: 20, + }, + { + person: 3, + sold: 40, + }, + { + person: 3, + sold: null, + }, + ]; + + var res = alasql('SELECT VALUE AVG(sold) FROM ?', [arr]); + assert.equal(res, 18.75); + done(); + }); + + it('4. Does not count null when using AVG and GROUP BY', function (done) { + var arr = [ + { + person: 1, + sold: 5, + }, + { + person: 1, + sold: null, + }, + { + person: 2, + sold: 10, + }, + { + person: 1, + sold: 20, + }, + { + person: 1, + sold: null, + }, + { + person: 3, + sold: 40, + }, + { + person: 3, + sold: null, + }, + ]; + + var res = alasql('SELECT person, avg(sold) FROM ? GROUP BY person', [arr]); + + assert(res, [ + {person: 1, 'AVG(sold)': 12.5}, + {person: 2, 'AVG(sold)': 10}, + {person: 3, 'AVG(sold)': 40}, + ]); + done(); + }); +});