Class AggregateNumerics
Long when it fits and a BigInteger otherwise (Snowflake's
NUMBER(38,0) range). A VARIANT input makes either aggregate DOUBLE (live-verified: SUM over
PARSE_JSON('1'), PARSE_JSON('2') is 3.0 with SYSTEM$TYPEOF FLOAT). AVG of fixed-point inputs is a
BigDecimal with scale = (max input scale) + 6, rounded HALF_UP (live-verified: AVG of the integers 90 and
95 is exactly 92.500000).-
Method Summary
Modifier and TypeMethodDescriptionstatic ObjectAVG overvalues(nulls are ignored).static ObjectSeesum(Iterable, boolean)— the same declared-VARIANT rule applied to AVG.static booleanisApproximateInput(Object value) Whether an accumulated input is APPROXIMATE, which keeps the whole result a double.static ObjectMEDIAN — the interpolating percentile at one half, and typed as one.static ObjectMEDIAN with the argument's declared tier — seepercentileCont(Iterable, double, boolean).static ObjectmedianOverCoerced(Iterable<Object> values) MEDIAN over a VARCHAR or VARIANT argument — seepercentileContOverCoerced(Iterable, double).static ObjectnonCumulativeWindowAvg(Iterable<Object> values, boolean variantArgument) AVG over a NON-CUMULATIVE window — a bareOVER (), a PARTITION BY, or an ORDER BY carrying a ROWS frame.static ObjectpercentileCont(Iterable<Object> values, double fraction) PERCENTILE_CONT — a value INTERPOLATED between two of the inputs, so it is a computed number and carries a computed scale: the widest input scale plus three, live-verified across seven NUMBER widths (a NUMBER(10,2) column gives NUMBER(13,5), and the value 2.00000 rather than 2.0).static ObjectpercentileCont(Iterable<Object> values, double fraction, boolean approximateArgument) PERCENTILE_CONT with the argument's DECLARED tier, which the values alone cannot always give: a FLOAT-declared value can still arrive in an exact carrier — computed exactly, or restored from an older snapshot — indistinguishable from an exact one, and only the declaration says there is no scale to build on.static ObjectpercentileContOverCoerced(Iterable<Object> values, double fraction) PERCENTILE_CONT over a VARCHAR or VARIANT key, which live neither reads at its decimals nor orders as numbers: every value is converted to a WHOLE number, NUMBER(9,0), and the inputs are ordered by their OWN type — text as text, so '10' sorts before '8' and '-2.5' before '0.5'.static ObjectpercentileDisc(Iterable<Object> values, double fraction) PERCENTILE_DISC — one of the inputs, handed back as it arrived.static ObjectpercentileDiscOverCoerced(Iterable<Object> values, double fraction) PERCENTILE_DISC over a VARCHAR or VARIANT key: the inputs ordered by their own type, as forpercentileContOverCoerced(Iterable, double), and the picked one handed back as the whole number it converts to — live declares it NUMBER(9,0) and answers 2 for the lower of '1.5' and '2.25'.static DoublerootOfDeclaredVariance(double variance, int maxInputScale, boolean approximate) The STDDEV family's value: the square root of the variance ROUNDED TO ITS OWN DECLARED SCALE.static ObjectrunningSum(Iterable<Object> values, boolean variantArgument) SUM read as a RUNNING sum: every value its own partial, so the double's last compensation is left unapplied (seePartialFloatSum).static intscaleOfInput(Object value) The scale an accumulated input contributes: a decimal's own, zero for an integral value.static ObjectSUM overvalues(nulls are ignored).static ObjectThevariantArgumentflag is for a SUM whose ARGUMENT is declared VARIANT even though the runtime values arrive as plain numbers — live,SUM(v:b)over whole-number JSON values is DOUBLE (7.0, SYSTEM$TYPEOF FLOAT): the declared type decides the tier exactly as a runtimeVariantValuedoes.static ObjectvarianceAtDeclaredScale(double variance, int maxInputScale, boolean approximate) A VARIANCE-family result presented at the scale its column DECLARES.static ObjectwindowAvg(List<? extends Iterable<Object>> partials, boolean variantArgument, boolean nonCumulative, boolean rowWise) AVG over a window frame given as the PARTIALS its double sum is read in, aswindowSum(List, boolean, boolean)reads SUM's — the whole partition one partial, a cumulative RANGE frame one per peer group, androwWisefor a running or sliding frame — at a cumulative window's scale, or three decimals narrower and truncated for every other shape (nonCumulativeWindowAvg(java.lang.Iterable<java.lang.Object>, boolean)).static ObjectSUM over a window frame given as the PARTIALS its double is read in (seePartialFloatSum): the whole partition is one partial, a cumulative RANGE frame one per peer group, androwWisemakes every value a partial of its own, as a running or sliding frame reads it.
-
Method Details
-
sum
SUM overvalues(nulls are ignored). Returns null when no non-null value is present (Snowflake SUM of an empty set is NULL). All-integer input yields a Long/BigInteger; any decimal/float/VARIANT input keeps the double sum (live-verified: SUM over a VARIANT column is DOUBLE even for whole-number JSON values).- Parameters:
values- the aggregated argument values, in group order- Returns:
- the sum — Long/BigInteger for all-integral input, BigDecimal for fixed-point, Double otherwise — or null for an empty set
-
sum
ThevariantArgumentflag is for a SUM whose ARGUMENT is declared VARIANT even though the runtime values arrive as plain numbers — live,SUM(v:b)over whole-number JSON values is DOUBLE (7.0, SYSTEM$TYPEOF FLOAT): the declared type decides the tier exactly as a runtimeVariantValuedoes.A DOUBLE sum is the aggregate's: added with Kahan compensation and read back with its last compensation applied — live, SUM(x * x) over 0.3 then 0.7 is 0.57999999999999984901, where the running sum is 0.57999999999999996003 (see
PartialFloatSum).- Parameters:
values- the aggregated argument values, in group ordervariantArgument- whether the argument expression is statically VARIANT-typed, which forces the DOUBLE tier- Returns:
- the sum on the tier the inputs select, or null for an empty set
-
runningSum
SUM read as a RUNNING sum: every value its own partial, so the double's last compensation is left unapplied (seePartialFloatSum). SUM(DISTINCT) answers this way — live, over 0.3, 0.7 and 0.3 squared it is 0.57999999999999996003 where SUM is 0.57999999999999984901. The exact tiers are the same sum either way.- Parameters:
values- the aggregated argument values, in group ordervariantArgument- whether the argument expression is statically VARIANT-typed- Returns:
- the sum on the tier the inputs select, or null for an empty set
-
windowSum
public static Object windowSum(List<? extends Iterable<Object>> partials, boolean variantArgument, boolean rowWise) SUM over a window frame given as the PARTIALS its double is read in (seePartialFloatSum): the whole partition is one partial, a cumulative RANGE frame one per peer group, androwWisemakes every value a partial of its own, as a running or sliding frame reads it.- Parameters:
partials- the frame's values, partial by partial, in partition ordervariantArgument- whether the argument expression is statically VARIANT-typedrowWise- whether every value is a partial of its own- Returns:
- the sum on the tier the inputs select, or null for an empty frame
-
avg
AVG overvalues(nulls are ignored). Returns null when no non-null value is present (Snowflake AVG of an empty set is NULL). All fixed-point input (Long/Integer/BigDecimal — not Double/Float) yields a BigDecimal with scale = (max input scale) + 6, rounded HALF_UP and with trailing zeros KEPT — AVG of the integers 90 and 95 is exactly 92.500000 and AVG(2, 2) renders 2.000000, matching live Snowflake. Any Double/Float or VARIANT input keeps the double average.- Parameters:
values- the aggregated argument values, in group order- Returns:
- the average — a scaled BigDecimal for all fixed-point input, a Double otherwise — or null for an empty set
-
avg
Seesum(Iterable, boolean)— the same declared-VARIANT rule applied to AVG.- Parameters:
values- the aggregated argument values, in group ordervariantArgument- whether the argument expression is statically VARIANT-typed, which keeps the average on the double path- Returns:
- the average on the tier the inputs select, or null for an empty set
-
nonCumulativeWindowAvg
AVG over a NON-CUMULATIVE window — a bareOVER (), a PARTITION BY, or an ORDER BY carrying a ROWS frame. Live declares three decimals wider than the input there rather than six, and TRUNCATES to that scale instead of rounding.Both halves are measured. Over NUMBER(10,2) the declared type is NUMBER(25,5) against the cumulative NUMBER(28,8); and seven rows summing to 1.00 average to 0.14285, where a half-up round of 0.142857142857… would give 0.14286. Rounding here would produce the wrong last digit.
A RANGE frame is CUMULATIVE and does not come here — see
WindowFunctionExpression.isRowsFramed.- Parameters:
values- the aggregated argument values, in partition ordervariantArgument- whether the argument is statically VARIANT, which keeps the double path- Returns:
- the average at the window's own declared scale, or null for an empty set
-
windowAvg
public static Object windowAvg(List<? extends Iterable<Object>> partials, boolean variantArgument, boolean nonCumulative, boolean rowWise) AVG over a window frame given as the PARTIALS its double sum is read in, aswindowSum(List, boolean, boolean)reads SUM's — the whole partition one partial, a cumulative RANGE frame one per peer group, androwWisefor a running or sliding frame — at a cumulative window's scale, or three decimals narrower and truncated for every other shape (nonCumulativeWindowAvg(java.lang.Iterable<java.lang.Object>, boolean)). Live, AVG(x * x) over 0.3 then 0.7 is 0.28999999999999992450 over the whole partition and 0.28999999999999998002 on a running frame's last row.- Parameters:
partials- the frame's values, partial by partial, in partition ordervariantArgument- whether the argument keeps the double path whatever its valuesnonCumulative- whether the window is not cumulative, which narrows and truncates the scalerowWise- whether every value is a partial of its own- Returns:
- the average, or null for an empty frame
-
median
MEDIAN — the interpolating percentile at one half, and typed as one.- Parameters:
values- the aggregated argument values, in group order- Returns:
- the median on the tier the inputs select, or null for an empty set
-
median
MEDIAN with the argument's declared tier — seepercentileCont(Iterable, double, boolean).- Parameters:
values- the aggregated argument values, in group orderapproximateArgument- whether the argument is declared FLOAT / DOUBLE / REAL- Returns:
- the median on the tier the declaration and the inputs select, or null for an empty set
-
percentileCont
PERCENTILE_CONT — a value INTERPOLATED between two of the inputs, so it is a computed number and carries a computed scale: the widest input scale plus three, live-verified across seven NUMBER widths (a NUMBER(10,2) column gives NUMBER(13,5), and the value 2.00000 rather than 2.0).The exact tier is what makes that possible. Collapsing every input to a double — as this did — loses the scale before there is anything to present at, and prints a small value in SCIENTIFIC notation besides: a median over NUMBER(5,4) came back as 2.0E-4 where live gives 0.0002000. A FLOAT or VARIANT input still selects the double tier, as it does for AVG and SUM.
- Parameters:
values- the aggregated argument values, in group orderfraction- the percentile, between 0 and 1- Returns:
- the interpolated value, or null for an empty set
-
percentileCont
public static Object percentileCont(Iterable<Object> values, double fraction, boolean approximateArgument) PERCENTILE_CONT with the argument's DECLARED tier, which the values alone cannot always give: a FLOAT-declared value can still arrive in an exact carrier — computed exactly, or restored from an older snapshot — indistinguishable from an exact one, and only the declaration says there is no scale to build on. Live answers a FLOAT percentile as the plain double — 2.5, not 2.5000.- Parameters:
values- the aggregated argument values, in group orderfraction- the percentile, between 0 and 1approximateArgument- whether the argument is declared FLOAT / DOUBLE / REAL- Returns:
- the interpolated value, or null for an empty set
-
percentileDisc
PERCENTILE_DISC — one of the inputs, handed back as it arrived. It computes nothing, so it adds nothing to the scale: the value already carries its column's, which is why this family was right all along wherever the value reached the caller unconverted.- Parameters:
values- the aggregated argument values, in group orderfraction- the percentile, between 0 and 1- Returns:
- the selected input value, or null for an empty set
-
medianOverCoerced
MEDIAN over a VARCHAR or VARIANT argument — seepercentileContOverCoerced(Iterable, double).- Parameters:
values- the aggregated argument values, in group order- Returns:
- the median of the whole numbers the values convert to, or null for an empty set
-
percentileContOverCoerced
PERCENTILE_CONT over a VARCHAR or VARIANT key, which live neither reads at its decimals nor orders as numbers: every value is converted to a WHOLE number, NUMBER(9,0), and the inputs are ordered by their OWN type — text as text, so '10' sorts before '8' and '-2.5' before '0.5'. The interpolation then runs between the converted neighbours, at the three extra decimals the family always adds. Live-verified: over '1.5' and '2.25' the median is 2.000 (each rounds to 2, half away from zero), over '2.5' and '3.5' it is 3.500, over '10', '9', '8' it is 8.000, over '-1.5', '-2.5', '0.5' it is -3.000, and a VARCHAR(4) and a VARCHAR(16777216) agree — the nine digits are the conversion's, not the column's.- Parameters:
values- the aggregated key values, in group orderfraction- the percentile, between 0 and 1- Returns:
- the interpolated value at scale three, or null for an empty set
-
percentileDiscOverCoerced
PERCENTILE_DISC over a VARCHAR or VARIANT key: the inputs ordered by their own type, as forpercentileContOverCoerced(Iterable, double), and the picked one handed back as the whole number it converts to — live declares it NUMBER(9,0) and answers 2 for the lower of '1.5' and '2.25'.- Parameters:
values- the aggregated key values, in group orderfraction- the percentile, between 0 and 1- Returns:
- the selected value's whole number, or null for an empty set
-
varianceAtDeclaredScale
public static Object varianceAtDeclaredScale(double variance, int maxInputScale, boolean approximate) A VARIANCE-family result presented at the scale its column DECLARES. The declared type isNUMBER(38, min(12, 2s + 6))for an exact input of scale s — the SQUARE of a scale, capped at twelve, the rule TypeInferencer already applies — and live pads the value out to it: over a NUMBER(10,2) column, VARIANCE answers 2.9166666667 and VARIANCE_POP answers 2.1875000000, both at ten decimals. Computing the statistic and then presenting it are separate steps, and only this one knows the scale.An APPROXIMATE input keeps the double: live types VARIANCE over a FLOAT as FLOAT, where a scaled decimal would render the other way.
-
rootOfDeclaredVariance
public static Double rootOfDeclaredVariance(double variance, int maxInputScale, boolean approximate) The STDDEV family's value: the square root of the variance ROUNDED TO ITS OWN DECLARED SCALE.Live-verified, and the reason the same three numbers give two different answers: STDDEV over NUMBER(38,0) is sqrt(2.333333) — the scale-6 variance — while over NUMBER(10,2) it is sqrt(2.3333333333), the scale-10 one. Live is not computing at a hidden precision; it takes the root of a variance that has already been rounded.
The result is always a DOUBLE, because live declares FLOAT for every input the family takes, NUMBER ones included — so it renders at the FLOAT text width rather than at a scale.
-
scaleOfInput
The scale an accumulated input contributes: a decimal's own, zero for an integral value. -
isApproximateInput
Whether an accumulated input is APPROXIMATE, which keeps the whole result a double.
-