1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Add support for the TOTAL() aggregate function - works like SUM() except

that it returns 0 instead of NULL when presented with an empty list. (CVS 2930)

FossilOrigin-Name: a7f528ff3446d50b280fb0b85063879e3ac5751a
This commit is contained in:
drh
2006-01-12 22:17:50 +00:00
parent 0e6082eb83
commit a97fdd3bfc
5 changed files with 39 additions and 19 deletions

View File

@ -1,5 +1,5 @@
C Performance\sboost\sin\ssqlite3VdbeRecordCompare.\s(CVS\s2929)
D 2006-01-12T20:28:35
C Add\ssupport\sfor\sthe\sTOTAL()\saggregate\sfunction\s-\sworks\slike\sSUM()\sexcept\nthat\sit\sreturns\s0\sinstead\sof\sNULL\swhen\spresented\swith\san\sempty\slist.\s(CVS\s2930)
D 2006-01-12T22:17:50
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -43,7 +43,7 @@ F src/date.c a927bdbb51296ac398d2f667086a7072c099e5ab
F src/delete.c c7bd5708a629585e073ce34cf3b1fcb52c2fef38
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
F src/expr.c 3b6acdb4e254027fe72ce70054ea6b71c7d423a3
F src/func.c e013c3b6c607c6a1654f5260eab59f5609a5ce4a
F src/func.c be4c026c1d2401f14c3186611e1131a895a3ca6e
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c a5595cf8d1d8ba087b676a63f1f7277ea44b5ac1
@ -202,7 +202,7 @@ F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80
F test/misc5.test a27520a0033f2837cda94bfdfb096a25fc4b128d
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
F test/null.test 012fe5455f4fc3102490b4bad373a674e5741fdd
F test/null.test db52272f9628ae9e77ab451cf0fb3871a98c5f00
F test/pager.test 1579e8f07291ae8e24db62ffade5c101c3e76597
F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
@ -319,7 +319,7 @@ F www/fullscanb.gif f7c94cb227f060511f8909e10f570157263e9a25
F www/index-ex1-x-b.gif f9b1d85c3fa2435cf38b15970c7e3aa1edae23a3
F www/index.tcl f84bf390bd272035934639748c89730f3d60dc44
F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1
F www/lang.tcl 6f81b2726dc350ba5dc0dd6dcddb9e7a307b9976
F www/lang.tcl b3561af8d85d2d712d43b3604e4aadce9257e4d9
F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 730ddb0b74ed23c916dabd7ce893bd6bc55f3549
R 36b85235284a365ef7c4f8a7c8bf02e6
P 14c423075bcebf42a3f4e24838bc865cfb90afda
R 96aa9577c2fe78f0881f3a139cc6dc0c
U drh
Z 308f9bd267f3ff57a7f1fa05f779432c
Z 680a9cdd5661322ac6544d3998d3b8d1

View File

@ -1 +1 @@
14c423075bcebf42a3f4e24838bc865cfb90afda
a7f528ff3446d50b280fb0b85063879e3ac5751a

View File

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.115 2006/01/09 16:12:05 danielk1977 Exp $
** $Id: func.c,v 1.116 2006/01/12 22:17:50 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -823,7 +823,13 @@ struct SumCtx {
};
/*
** Routines used to compute the sum or average.
** Routines used to compute the sum, average, and total.
**
** The SUM() function follows the (broken) SQL standard which means
** that it returns NULL if it sums over no inputs. TOTAL returns
** 0.0 in that case. In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
** value.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
@ -857,6 +863,11 @@ static void avgFinalize(sqlite3_context *context){
sqlite3_result_double(context, p->sum/(double)p->cnt);
}
}
static void totalFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_double(context, p ? p->sum : 0.0);
}
/*
** An instance of the following structure holds the context of a
@ -1000,6 +1011,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
{ "sum", 1, 0, 0, sumStep, sumFinalize },
{ "total", 1, 0, 0, sumStep, totalFinalize },
{ "avg", 1, 0, 0, sumStep, avgFinalize },
{ "count", 0, 0, 0, countStep, countFinalize },
{ "count", 1, 0, 0, countStep, countFinalize },

View File

@ -102,6 +102,14 @@ do_test null-3.1 {
}
} {7 4 6 2 3 0.5 0.5 0 1}
# The sum of zero entries is a NULL, but the total of zero entries is 0.
#
do_test null-3.2 {
execsql {
SELECT sum(b), total(b) FROM t1 WHERE b<0
}
} {{} 0.0}
# Check to see how WHERE clauses handle NULL values. A NULL value
# is the same as UNKNOWN. The WHERE clause should only select those
# rows that are TRUE. FALSE and UNKNOWN rows are rejected.

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the lang-*.html files.
#
set rcsid {$Id: lang.tcl,v 1.104 2006/01/04 15:58:29 drh Exp $}
set rcsid {$Id: lang.tcl,v 1.105 2006/01/12 22:17:50 drh Exp $}
source common.tcl
if {[llength $argv]>0} {
@ -1395,15 +1395,15 @@ if all values in the group are NULL.</td>
</tr>
<tr>
<td valign="top" align="right">sum(<i>X</i>)</td>
<td valign="top" align="right">sum(<i>X</i>)<br>total(<i>X</i>)</td>
<td valign="top">Return the numeric sum of all numeric values in the group.
If there are no input rows or all values are NULL, then NULL is returned.
If there are no input rows or all values are NULL, then sum() returns
NULL but total() returns zero.
NULL is not a helpful result in that case (the correct answer should be
zero) but it is what the SQL standard requires and how
most other SQL database engines operate so SQLite does it that way
in order to be compatible.
You will probably want to use
"<b>coalesce(sum(</b>X<b>),0)</b>" instead of just "<b>sum(</b>X<b>)</b>"
zero) but the SQL standard requires that behavior from sum() and that is how
most other SQL database engines implement sum() so SQLite does it that way
in order to be compatible. The non-standard total() function is provided
as a convenient way
to work around this design problem in the SQL language.</td>
</tr>
</table>