Percentiles, Statistics, And Regression
Generic Description
Use this family when you need distribution shape, spread, relationship strength, or linear fit instead of only totals and averages. Documenting it separately matters because aggregate placement changes row grain, grouping behavior, and whether state/merge forms are valid.
Simple example:
MATCH (s:SessionMetric)
RETURN percentile_disc(s.score, 0.5) AS median_score,
variance(s.score) AS score_variance,
stDevP(s.score) AS score_stddev_pop
Consumer-Level Explanation
This family answers richer analytical questions such as:
- where is the median or percentile boundary?
- how spread out are values?
- how strongly do two measures move together?
- what is the slope or fit quality of a simple linear trend?
The current implemented surface includes:
- percentiles:
percentile_disc,percentile_cont - spread/statistics:
stDev,stDevP,variance,varPop - covariance/correlation:
covarSamp,covarPop,corr - regression:
regrSlope,regrIntercept,regrR2,regrCount,regrSxx,regrSyy,regrSxy,regrAvgx,regrAvgy
These are the difference between a dashboard that only counts events and one that actually helps you understand distributions and relationships.
More Detailed Explanation
percentile_disc and percentile_cont are not interchangeable:
- discrete percentile returns an observed value from the ordered population
- continuous percentile interpolates between neighboring values
That matters when you are modeling durations, prices, scores, or latencies and need to know whether the returned value must be one of the original observations.
The spread and regression families are implemented as mathematically explicit state machines rather than ad hoc recomputation shortcuts. That matters because the same engine now supports:
- direct aggregate use
- partial-state emission
- state merge
- spill-backed grouped execution for the supported exact subset
- exact incremental materialized-view maintenance for the safe query subset
The current implementation also widened exact support for several DISTINCT shapes:
- grouped spill-backed
DISTINCTstats and percentiles - exact incremental aggregate views for
DISTINCT percentile_discandDISTINCT percentile_cont
That keeps distribution-aware analytics usable without inventing a second analytical runtime.
Advanced Example
MATCH (u:User)-[:HAS_APP_SESSION]->(s:AppSession)
TIME s.started_at BETWEEN datetime('2026-04-01T00:00:00Z') AND datetime('2026-04-30T23:59:59Z')
RETURN u.profile.location.country AS country,
percentile_disc(DISTINCT s.duration_seconds, 0.5) AS median_disc_duration,
percentile_cont(DISTINCT s.duration_seconds, 0.95) AS p95_cont_duration,
variance(s.duration_seconds) AS duration_variance,
stDevP(s.duration_seconds) AS duration_stddev_pop,
corr(s.engagement_score, s.duration_seconds) AS score_duration_corr,
regrSlope(s.engagement_score, s.duration_seconds) AS score_duration_slope,
regrR2(s.engagement_score, s.duration_seconds) AS score_duration_fit
ORDER BY country
Real Use Cases
- latency and session-duration reporting where percentiles are more meaningful than averages
- product analytics where variance and standard deviation reveal inconsistent user behavior
- engagement or sensor data where correlation and regression reveal whether one metric moves with another
- time-bucketed social or operational reporting where linear fit helps identify trend strength
Real Limitations And Tradeoffs
- statistical and regression outputs are only meaningful when the underlying sample design makes sense; the engine can compute them correctly but cannot fix poor modeling
- percentiles over very broad groups may still be computationally heavier than simple scalar summaries
- correlation does not imply causation; users still need domain interpretation