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:
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Performance\sboost\sin\ssqlite3VdbeRecordCompare.\s(CVS\s2929)
|
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-12T20:28:35
|
D 2006-01-12T22:17:50
|
||||||
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
|
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
|
||||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -43,7 +43,7 @@ F src/date.c a927bdbb51296ac398d2f667086a7072c099e5ab
|
|||||||
F src/delete.c c7bd5708a629585e073ce34cf3b1fcb52c2fef38
|
F src/delete.c c7bd5708a629585e073ce34cf3b1fcb52c2fef38
|
||||||
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
|
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
|
||||||
F src/expr.c 3b6acdb4e254027fe72ce70054ea6b71c7d423a3
|
F src/expr.c 3b6acdb4e254027fe72ce70054ea6b71c7d423a3
|
||||||
F src/func.c e013c3b6c607c6a1654f5260eab59f5609a5ce4a
|
F src/func.c be4c026c1d2401f14c3186611e1131a895a3ca6e
|
||||||
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
|
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
|
||||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||||
F src/insert.c a5595cf8d1d8ba087b676a63f1f7277ea44b5ac1
|
F src/insert.c a5595cf8d1d8ba087b676a63f1f7277ea44b5ac1
|
||||||
@ -202,7 +202,7 @@ F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80
|
|||||||
F test/misc5.test a27520a0033f2837cda94bfdfb096a25fc4b128d
|
F test/misc5.test a27520a0033f2837cda94bfdfb096a25fc4b128d
|
||||||
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
|
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
|
||||||
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
||||||
F test/null.test 012fe5455f4fc3102490b4bad373a674e5741fdd
|
F test/null.test db52272f9628ae9e77ab451cf0fb3871a98c5f00
|
||||||
F test/pager.test 1579e8f07291ae8e24db62ffade5c101c3e76597
|
F test/pager.test 1579e8f07291ae8e24db62ffade5c101c3e76597
|
||||||
F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e
|
F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e
|
||||||
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
|
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-ex1-x-b.gif f9b1d85c3fa2435cf38b15970c7e3aa1edae23a3
|
||||||
F www/index.tcl f84bf390bd272035934639748c89730f3d60dc44
|
F www/index.tcl f84bf390bd272035934639748c89730f3d60dc44
|
||||||
F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1
|
F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1
|
||||||
F www/lang.tcl 6f81b2726dc350ba5dc0dd6dcddb9e7a307b9976
|
F www/lang.tcl b3561af8d85d2d712d43b3604e4aadce9257e4d9
|
||||||
F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
|
F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
|
||||||
F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
|
F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
|
||||||
F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
|
F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
|
||||||
@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||||
P 730ddb0b74ed23c916dabd7ce893bd6bc55f3549
|
P 14c423075bcebf42a3f4e24838bc865cfb90afda
|
||||||
R 36b85235284a365ef7c4f8a7c8bf02e6
|
R 96aa9577c2fe78f0881f3a139cc6dc0c
|
||||||
U drh
|
U drh
|
||||||
Z 308f9bd267f3ff57a7f1fa05f779432c
|
Z 680a9cdd5661322ac6544d3998d3b8d1
|
||||||
|
@ -1 +1 @@
|
|||||||
14c423075bcebf42a3f4e24838bc865cfb90afda
|
a7f528ff3446d50b280fb0b85063879e3ac5751a
|
16
src/func.c
16
src/func.c
@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** 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 "sqliteInt.h"
|
||||||
#include <ctype.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){
|
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||||
SumCtx *p;
|
SumCtx *p;
|
||||||
@ -857,6 +863,11 @@ static void avgFinalize(sqlite3_context *context){
|
|||||||
sqlite3_result_double(context, p->sum/(double)p->cnt);
|
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
|
** 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 },
|
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
|
||||||
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
|
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
|
||||||
{ "sum", 1, 0, 0, sumStep, sumFinalize },
|
{ "sum", 1, 0, 0, sumStep, sumFinalize },
|
||||||
|
{ "total", 1, 0, 0, sumStep, totalFinalize },
|
||||||
{ "avg", 1, 0, 0, sumStep, avgFinalize },
|
{ "avg", 1, 0, 0, sumStep, avgFinalize },
|
||||||
{ "count", 0, 0, 0, countStep, countFinalize },
|
{ "count", 0, 0, 0, countStep, countFinalize },
|
||||||
{ "count", 1, 0, 0, countStep, countFinalize },
|
{ "count", 1, 0, 0, countStep, countFinalize },
|
||||||
|
@ -102,6 +102,14 @@ do_test null-3.1 {
|
|||||||
}
|
}
|
||||||
} {7 4 6 2 3 0.5 0.5 0 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
|
# Check to see how WHERE clauses handle NULL values. A NULL value
|
||||||
# is the same as UNKNOWN. The WHERE clause should only select those
|
# is the same as UNKNOWN. The WHERE clause should only select those
|
||||||
# rows that are TRUE. FALSE and UNKNOWN rows are rejected.
|
# rows that are TRUE. FALSE and UNKNOWN rows are rejected.
|
||||||
|
16
www/lang.tcl
16
www/lang.tcl
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Run this Tcl script to generate the lang-*.html files.
|
# 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
|
source common.tcl
|
||||||
|
|
||||||
if {[llength $argv]>0} {
|
if {[llength $argv]>0} {
|
||||||
@ -1395,15 +1395,15 @@ if all values in the group are NULL.</td>
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<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.
|
<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
|
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
|
zero) but the SQL standard requires that behavior from sum() and that is how
|
||||||
most other SQL database engines operate so SQLite does it that way
|
most other SQL database engines implement sum() so SQLite does it that way
|
||||||
in order to be compatible.
|
in order to be compatible. The non-standard total() function is provided
|
||||||
You will probably want to use
|
as a convenient way
|
||||||
"<b>coalesce(sum(</b>X<b>),0)</b>" instead of just "<b>sum(</b>X<b>)</b>"
|
|
||||||
to work around this design problem in the SQL language.</td>
|
to work around this design problem in the SQL language.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
Reference in New Issue
Block a user