(
&mut self,
expr: Expr<Aug>,
filter: Option<Box<Expr<Aug>>>,
distinct: bool,
sample: bool,
over: Option<WindowSpec<Aug>>,
)
| 205 | } |
| 206 | |
| 207 | fn plan_variance( |
| 208 | &mut self, |
| 209 | expr: Expr<Aug>, |
| 210 | filter: Option<Box<Expr<Aug>>>, |
| 211 | distinct: bool, |
| 212 | sample: bool, |
| 213 | over: Option<WindowSpec<Aug>>, |
| 214 | ) -> Expr<Aug> { |
| 215 | // N.B. this variance calculation uses the "textbook" algorithm, which |
| 216 | // is known to accumulate problematic amounts of error. The numerically |
| 217 | // stable variants, the most well-known of which is Welford's, are |
| 218 | // however difficult to implement inside of Differential Dataflow, as |
| 219 | // they do not obviously support retractions efficiently (database-issues#436). |
| 220 | // |
| 221 | // The code below converts var_samp(x) into |
| 222 | // |
| 223 | // (sum(x²) - sum(x)² / count(x)) / (count(x) - 1) |
| 224 | // |
| 225 | // and var_pop(x) into: |
| 226 | // |
| 227 | // (sum(x²) - sum(x)² / count(x)) / count(x) |
| 228 | // |
| 229 | let expr = expr.call_unary( |
| 230 | self.scx |
| 231 | .dangerous_resolve_name(vec![MZ_UNSAFE_SCHEMA, "mz_avg_promotion"]), |
| 232 | ); |
| 233 | let expr_squared = expr.clone().multiply(expr.clone()); |
| 234 | let sum_squares = self.plan_agg( |
| 235 | self.scx |
| 236 | .dangerous_resolve_name(vec![PG_CATALOG_SCHEMA, "sum"]), |
| 237 | expr_squared, |
| 238 | vec![], |
| 239 | filter.clone(), |
| 240 | distinct, |
| 241 | over.clone(), |
| 242 | ); |
| 243 | let sum = self.plan_agg( |
| 244 | self.scx |
| 245 | .dangerous_resolve_name(vec![PG_CATALOG_SCHEMA, "sum"]), |
| 246 | expr.clone(), |
| 247 | vec![], |
| 248 | filter.clone(), |
| 249 | distinct, |
| 250 | over.clone(), |
| 251 | ); |
| 252 | let sum_squared = sum.clone().multiply(sum); |
| 253 | let count = self.plan_agg( |
| 254 | self.scx |
| 255 | .dangerous_resolve_name(vec![PG_CATALOG_SCHEMA, "count"]), |
| 256 | expr, |
| 257 | vec![], |
| 258 | filter, |
| 259 | distinct, |
| 260 | over, |
| 261 | ); |
| 262 | let result = Self::plan_divide( |
| 263 | sum_squares.minus(Self::plan_divide(sum_squared, count.clone())), |
| 264 | if sample { |
no test coverage detected