Build histogram aggregation CTEs
(self, prefix: str, group_cols: List[str],
duration_col: str, bucket_col: str)
| 713 | FROM base_samples bs""" |
| 714 | |
| 715 | def _build_histogram_cte(self, prefix: str, group_cols: List[str], |
| 716 | duration_col: str, bucket_col: str) -> List[str]: |
| 717 | """Build histogram aggregation CTEs""" |
| 718 | ctes = [] |
| 719 | |
| 720 | # Filter group columns to exclude aggregates (case-insensitive) |
| 721 | hist_group_cols = [col for col in group_cols |
| 722 | if col.lower() not in ['samples', 'avg_threads', 'sclat_histogram', 'iolat_histogram'] |
| 723 | and not col.lower().startswith('sc.') and not col.lower().startswith('io.')] |
| 724 | |
| 725 | # Build aggregation CTE |
| 726 | agg_cte = f"""{prefix}_bucket_counts AS ( |
| 727 | SELECT |
| 728 | {', '.join(hist_group_cols)}, |
| 729 | {bucket_col}, |
| 730 | COUNT(*) as cnt, |
| 731 | COUNT(*) * {bucket_col} / 1000000.0 as est_time_s |
| 732 | FROM base_samples |
| 733 | WHERE {duration_col} > 0 AND {bucket_col} IS NOT NULL |
| 734 | GROUP BY {', '.join(hist_group_cols)}, {bucket_col} |
| 735 | )""" |
| 736 | ctes.append(agg_cte) |
| 737 | |
| 738 | # Build max calculation CTE |
| 739 | max_cte = f"""{prefix}_bucket_with_max AS ( |
| 740 | SELECT |
| 741 | *, |
| 742 | MAX(est_time_s) OVER () as {prefix}_global_max_time |
| 743 | FROM {prefix}_bucket_counts |
| 744 | )""" |
| 745 | ctes.append(max_cte) |
| 746 | |
| 747 | return ctes |
| 748 | |
| 749 | def _build_final_select(self, group_cols: List[str], |
| 750 | latency_columns: Optional[List[str]], |