Skip to content

Commit 649af5e

Browse files
committed
Merge pull request #7 from lorenzhs/quantile
Add quantiles to sqlite functions
2 parents 7ce050b + 403be83 commit 649af5e

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

src/sqlite-functions.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,25 @@ struct ModeCtx {
14061406
int done; /* whether the answer has been found */
14071407
};
14081408

1409+
/*
1410+
** Like ModeCtx, but with an additional integer or double argument.
1411+
** Used for computing arbitrary quantiles as aggregates with quantile()
1412+
*/
1413+
typedef struct ModeArgCtx ModeArgCtx;
1414+
struct ModeArgCtx {
1415+
i64 riM; /* integer value found so far */
1416+
double rdM; /* double value found so far */
1417+
i64 cnt; /* number of elements so far */
1418+
double pcnt; /* number of elements smaller than a percentile */
1419+
i64 mcnt; /* maximum number of occurrences (for mode) */
1420+
i64 mn; /* number of occurrences (for mode and percentiles) */
1421+
i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */
1422+
map* m; /* map structure used for the computation */
1423+
i64 argi; /* integer argument */
1424+
double argd; /* double argument */
1425+
int done; /* whether the answer has been found */
1426+
};
1427+
14091428
/*
14101429
** called for each value received during a calculation of stdev or variance
14111430
*/
@@ -1474,6 +1493,63 @@ static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){
14741493
}
14751494
}
14761495

1496+
1497+
/*
1498+
** called for each value received during a calculation of mode of median
1499+
*/
1500+
static void modeStepArg(sqlite3_context *context, int argc, sqlite3_value **argv){
1501+
ModeArgCtx *p;
1502+
i64 xi=0;
1503+
double xd=0.0;
1504+
i64 *iptr;
1505+
double *dptr;
1506+
int type1, type2;
1507+
1508+
ASSERT( argc==2 );
1509+
type1 = sqlite3_value_numeric_type(argv[0]);
1510+
type2 = sqlite3_value_numeric_type(argv[1]);
1511+
1512+
if( type1 == SQLITE_NULL || type2 == SQLITE_NULL)
1513+
return;
1514+
1515+
p = (ModeArgCtx*)sqlite3_aggregate_context(context, sizeof(*p));
1516+
1517+
if( 0==(p->m) ){
1518+
p->m = (map*)calloc(1, sizeof(map));
1519+
if( type1==SQLITE_INTEGER ){
1520+
/* map will be used for integers */
1521+
*(p->m) = map_make(int_cmp);
1522+
p->is_double = 0;
1523+
}else{
1524+
p->is_double = 1;
1525+
/* map will be used for doubles */
1526+
*(p->m) = map_make(double_cmp);
1527+
}
1528+
/* parse the argument */
1529+
if( type2==SQLITE_INTEGER ){
1530+
/* integer argument */
1531+
p->argi = sqlite3_value_int64(argv[0]);
1532+
}else{
1533+
/* double argument */
1534+
p->argd = sqlite3_value_double(argv[1]);
1535+
}
1536+
}
1537+
1538+
++(p->cnt);
1539+
1540+
if( 0==p->is_double ){
1541+
xi = sqlite3_value_int64(argv[0]);
1542+
iptr = (i64*)calloc(1,sizeof(i64));
1543+
*iptr = xi;
1544+
map_insert(p->m, iptr);
1545+
}else{
1546+
xd = sqlite3_value_double(argv[0]);
1547+
dptr = (double*)calloc(1,sizeof(double));
1548+
*dptr = xd;
1549+
map_insert(p->m, dptr);
1550+
}
1551+
}
1552+
14771553
/*
14781554
** Auxiliary function that iterates all elements in a map and finds the mode
14791555
** (most frequent value)
@@ -1623,6 +1699,20 @@ static void upper_quartileFinalize(sqlite3_context *context){
16231699
}
16241700
}
16251701

1702+
/*
1703+
** Returns an arbitrary quantile
1704+
** The quantile was passed to the step function
1705+
*/
1706+
static void quantileFinalize(sqlite3_context *context){
1707+
ModeArgCtx *p;
1708+
p = (ModeArgCtx*) sqlite3_aggregate_context(context, 0);
1709+
if( p!=0 ){
1710+
/* quantile is stored in p->arg */
1711+
p->pcnt = (p->cnt)*(p->argd);
1712+
_medianFinalize(context);
1713+
}
1714+
}
1715+
16261716
/*
16271717
** Returns the stdev value
16281718
*/
@@ -1812,6 +1902,7 @@ int RegisterExtensionFunctions(sqlite3 *db){
18121902
{ "median", 1, 0, 0, modeStep, medianFinalize },
18131903
{ "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize },
18141904
{ "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize },
1905+
{ "quantile", 2, 0, 0, modeStepArg, quantileFinalize },
18151906
};
18161907
unsigned int i;
18171908

0 commit comments

Comments
 (0)