sql_cli/refactoring/
conditional_agg.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Serialize, Deserialize)]
6pub struct ConditionalAggregation {
7 pub column: String,
8 pub values: Vec<String>,
9 pub aggregate_func: AggregateFunction,
10 pub aggregate_column: Option<String>,
11}
12
13#[derive(Debug, Serialize, Deserialize)]
14pub enum AggregateFunction {
15 Count,
16 Sum,
17 Avg,
18 Max,
19 Min,
20}
21
22impl ConditionalAggregation {
23 pub fn to_sql(&self) -> Vec<String> {
25 let mut statements = Vec::new();
26
27 for value in &self.values {
28 let condition = format!("{} = '{}'", self.column, value);
29
30 let agg_expr = match &self.aggregate_func {
31 AggregateFunction::Count => {
32 format!("SUM(CASE WHEN {} THEN 1 ELSE 0 END)", condition)
33 }
34 AggregateFunction::Sum => {
35 let default_col = "1".to_string();
36 let col = self.aggregate_column.as_ref().unwrap_or(&default_col);
37 format!("SUM(CASE WHEN {} THEN {} ELSE 0 END)", condition, col)
38 }
39 AggregateFunction::Avg => {
40 let default_col = "1".to_string();
41 let col = self.aggregate_column.as_ref().unwrap_or(&default_col);
42 format!("AVG(CASE WHEN {} THEN {} ELSE NULL END)", condition, col)
43 }
44 AggregateFunction::Max => {
45 let col = self.aggregate_column.as_ref().unwrap_or(&self.column);
46 format!("MAX(CASE WHEN {} THEN {} ELSE NULL END)", condition, col)
47 }
48 AggregateFunction::Min => {
49 let col = self.aggregate_column.as_ref().unwrap_or(&self.column);
50 format!("MIN(CASE WHEN {} THEN {} ELSE NULL END)", condition, col)
51 }
52 };
53
54 let alias = format!(
56 "{}_{}",
57 value.to_lowercase().replace(' ', "_"),
58 match &self.aggregate_func {
59 AggregateFunction::Count => "count",
60 AggregateFunction::Sum => "sum",
61 AggregateFunction::Avg => "avg",
62 AggregateFunction::Max => "max",
63 AggregateFunction::Min => "min",
64 }
65 );
66
67 statements.push(format!("{} AS {}", agg_expr, alias));
68 }
69
70 statements
71 }
72
73 pub fn balance_pattern(
75 positive_condition: &str,
76 negative_condition: &str,
77 column: &str,
78 ) -> String {
79 format!(
80 r#"SUM(CASE WHEN {} THEN {} ELSE 0 END) -
81SUM(CASE WHEN {} THEN {} ELSE 0 END) AS net_balance"#,
82 positive_condition, column, negative_condition, column
83 )
84 }
85}