# Ceph Path Coldness Score Cluster-Level Statistics (MySQL)

## Prompt
Please generate MySQL code based on the following requirements.

1. Task Objective
Perform cluster-level statistics on Ceph path coldness score data using three aggregation methods, and write the results to the target table.

2. Input
- Input table: `internal_platform_db.t_ceph_path_coldness_score_v2_mysql_004`
- Filter condition: `dt='20260507'`

3. Processing Rules
3.1 Three path selection method definitions:
- `level2_only`: Select only records where `path_level=2`
- `max_available`: For each `cluster_name`, group by the first-level directory of `path_level2` (group key = the first segment obtained by removing the leading `/` from `path_level2` and splitting by `/`; for example, `/data/logs` and `/data/backup` both have the group key `data`). For each group, select the record with the maximum `path_level`.
- `leaf_only`: Select leaf nodes (i.e., records for which no other record with the same `cluster_name` exists whose `path_level2` equals the parent path obtained by removing the last `/` and everything after it from the current record's `path_level2`; for example, if the current path is `/data/logs/app1`, the parent path is `/data/logs`, and if a record with this parent path exists, the current record is not a leaf).

3.2 After merging the data from all three methods, aggregate by `cluster_name` and `agg_method`:
- `total_path_count`: Total path count (count)
- `total_size_tb`: Total capacity in TB (sum)
- `total_access_count`: Total access count (sum)
- `avg_coldness_score`: Average coldness score (mean)
- `cluster_heat_category`: Categorize based on `avg_coldness_score`: >=60 is `'高热集群'` (high-heat cluster), >=40 is `'较热集群'` (warm cluster), >=20 is `'中等集群'` (moderate cluster), otherwise `'较冷集群'` (cool cluster)
- `p0_count`/`p0_size_tb`: Path count/capacity where `governance_level='P0'`
- `p1_count`/`p1_size_tb`: Path count/capacity where `governance_level='P1'`
- `p2_count`/`p2_size_tb`: Path count/capacity where `governance_level='P2'`
- `p3_count`/`p3_size_tb`: Path count/capacity where `governance_level='P3'`
- `cold_path_pct`: (P0 path count + P1 path count) / total path count * 100
- `cold_size_pct`: (P0 capacity + P1 capacity) / total capacity * 100

4. Output Requirements
Output field order: `cluster_name` (VARCHAR(256)), `agg_method` (VARCHAR(256)), `total_path_count` (BIGINT), `total_size_tb` (DOUBLE), `total_access_count` (BIGINT), `avg_coldness_score` (DOUBLE), `cluster_heat_category` (VARCHAR(256)), `p0_count` (BIGINT), `p0_size_tb` (DOUBLE), `p1_count` (BIGINT), `p1_size_tb` (DOUBLE), `p2_count` (BIGINT), `p2_size_tb` (DOUBLE), `p3_count` (BIGINT), `p3_size_tb` (DOUBLE), `cold_path_pct` (DOUBLE), `cold_size_pct` (DOUBLE), `dt` (VARCHAR(256))

5. Write Requirements
- Output table: `internal_platform_db.t_ceph_coldness_cluster_stats_v2_cand_mysql_004`
- Filter condition: `dt='20260507'`
- No joins, single-table processing
- Use standard MySQL syntax; do not use Hive/Spark SQL dialects

**Environment and Execution Notes**:
- Your final output must be written to the file `/tmp_workspace/result.py`, not `result.sql`
- The local MySQL is running at localhost:3306, username `root`, password `root123`
- Use Python `pymysql` in `result.py` to execute the SQL (do not use the `mysql` command-line tool)
- The script must include complete table creation (if the target table does not exist) and data writing logic
- After writing `result.py`, you must execute `python3 /tmp_workspace/result.py` yourself to verify that it runs successfully and produces correct data

## Reference Solution
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
mysql_004 ground truth: Ceph路径冷热评分集群级统计

Task:
  对 t_ceph_path_coldness_score_v2_mysql_004 进行三种聚合方式统计，
  结果写入 t_ceph_coldness_cluster_stats_v2_cand_mysql_004
"""
import pymysql
import sys

DB_NAME = "internal_platform_db"
INPUT_TABLE = "t_ceph_path_coldness_score_v2_mysql_004"
OUTPUT_TABLE = "t_ceph_coldness_cluster_stats_v2_cand_mysql_004"

MYSQL_CONFIG = {
    "host": "localhost",
    "port": 3306,
    "user": "root",
    "password": "root123",
    "charset": "utf8mb4",
}

gt_sql = f"""
INSERT INTO {DB_NAME}.{OUTPUT_TABLE}
    (cluster_name, agg_method, total_path_count, total_size_tb, total_access_count,
     avg_coldness_score, cluster_heat_category,
     p0_count, p0_size_tb, p1_count, p1_size_tb,
     p2_count, p2_size_tb, p3_count, p3_size_tb,
     cold_path_pct, cold_size_pct, dt)

WITH all_scores AS (
    SELECT *
    FROM {DB_NAME}.{INPUT_TABLE}
    WHERE dt = '20260507'
),

-- Method 1: Fixed path_level=2
level2_data AS (
    SELECT *, 'level2_only' AS agg_method
    FROM all_scores
    WHERE path_level = 2
),

-- Method 2: Maximum available level per path tree
max_avail_data AS (
    SELECT a.*, 'max_available' AS agg_method
    FROM all_scores a
    INNER JOIN (
        SELECT
            cluster_name,
            path_level2,
            path_level,
            ROW_NUMBER() OVER (
                PARTITION BY cluster_name,
                    SUBSTRING_INDEX(TRIM(LEADING '/' FROM path_level2), '/', 1)
                ORDER BY path_level DESC, path_level2
            ) AS rn
        FROM all_scores
    ) b
    ON a.cluster_name = b.cluster_name
       AND a.path_level2 = b.path_level2
       AND a.path_level = b.path_level
       AND b.rn = 1
),

-- Method 3: Leaf nodes only (no deeper children)
parent_paths AS (
    SELECT DISTINCT
        cluster_name,
        path_level - 1 AS parent_level,
        REGEXP_REPLACE(path_level2, '/[^/]+$', '') AS parent_path
    FROM all_scores
    WHERE path_level >= 2
),

leaf_data AS (
    SELECT a.*, 'leaf_only' AS agg_method
    FROM all_scores a
    LEFT JOIN parent_paths b
        ON a.cluster_name = b.cluster_name
        AND a.path_level = b.parent_level
        AND a.path_level2 = b.parent_path
    WHERE b.parent_path IS NULL
),

-- Combine three methods
union_all AS (
    SELECT * FROM level2_data
    UNION ALL
    SELECT * FROM max_avail_data
    UNION ALL
    SELECT * FROM leaf_data
)

-- Aggregate by cluster and method
SELECT
    cluster_name,
    agg_method,
    COUNT(*) AS total_path_count,
    ROUND(SUM(size_tb), 2) AS total_size_tb,
    SUM(access_count) AS total_access_count,
    ROUND(AVG(coldness_score), 2) AS avg_coldness_score,

    CASE
        WHEN AVG(coldness_score) >= 60 THEN '高热集群'
        WHEN AVG(coldness_score) >= 40 THEN '较热集群'
        WHEN AVG(coldness_score) >= 20 THEN '中等集群'
        ELSE '较冷集群'
    END AS cluster_heat_category,

    SUM(CASE WHEN governance_level = 'P0' THEN 1 ELSE 0 END) AS p0_count,
    ROUND(SUM(CASE WHEN governance_level = 'P0' THEN size_tb ELSE 0 END), 2) AS p0_size_tb,
    SUM(CASE WHEN governance_level = 'P1' THEN 1 ELSE 0 END) AS p1_count,
    ROUND(SUM(CASE WHEN governance_level = 'P1' THEN size_tb ELSE 0 END), 2) AS p1_size_tb,
    SUM(CASE WHEN governance_level = 'P2' THEN 1 ELSE 0 END) AS p2_count,
    ROUND(SUM(CASE WHEN governance_level = 'P2' THEN size_tb ELSE 0 END), 2) AS p2_size_tb,
    SUM(CASE WHEN governance_level = 'P3' THEN 1 ELSE 0 END) AS p3_count,
    ROUND(SUM(CASE WHEN governance_level = 'P3' THEN size_tb ELSE 0 END), 2) AS p3_size_tb,

    ROUND(SUM(CASE WHEN governance_level IN ('P0','P1') THEN 1 ELSE 0 END)
          * 100.0 / COUNT(*), 2) AS cold_path_pct,
    ROUND(SUM(CASE WHEN governance_level IN ('P0','P1') THEN size_tb ELSE 0 END)
          * 100.0 / NULLIF(SUM(size_tb), 0), 2) AS cold_size_pct,

    '20260507' AS dt

FROM union_all
GROUP BY cluster_name, agg_method
"""


def main():
    conn = pymysql.connect(**MYSQL_CONFIG)

    try:
        with conn.cursor() as cur:
            # Ensure output table exists
            cur.execute(f"""
                CREATE TABLE IF NOT EXISTS {DB_NAME}.{OUTPUT_TABLE} (
                    cluster_name        VARCHAR(256) COMMENT '集群名',
                    agg_method          VARCHAR(256) COMMENT '聚合方式',
                    total_path_count    BIGINT COMMENT '路径总数',
                    total_size_tb       DOUBLE COMMENT '总容量(TB)',
                    total_access_count  BIGINT COMMENT '总访问次数',
                    avg_coldness_score  DOUBLE COMMENT '平均冷热评分',
                    cluster_heat_category VARCHAR(256) COMMENT '集群热度分类',
                    p0_count            BIGINT COMMENT 'P0路径数',
                    p0_size_tb          DOUBLE COMMENT 'P0容量TB',
                    p1_count            BIGINT COMMENT 'P1路径数',
                    p1_size_tb          DOUBLE COMMENT 'P1容量TB',
                    p2_count            BIGINT COMMENT 'P2路径数',
                    p2_size_tb          DOUBLE COMMENT 'P2容量TB',
                    p3_count            BIGINT COMMENT 'P3路径数',
                    p3_size_tb          DOUBLE COMMENT 'P3容量TB',
                    cold_path_pct       DOUBLE COMMENT '冷路径占比',
                    cold_size_pct       DOUBLE COMMENT '冷容量占比',
                    dt                  VARCHAR(256) COMMENT '数据日期'
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            """)

            # Truncate + insert
            cur.execute(f"TRUNCATE TABLE {DB_NAME}.{OUTPUT_TABLE}")
            cur.execute(gt_sql)

        conn.commit()
        print("mysql_004 ground_truth done: rows written to output table")
    except Exception as e:
        print(f"ground_truth error: {e}", file=sys.stderr)
        conn.rollback()
        sys.exit(1)
    finally:
        conn.close()


if __name__ == "__main__":
    main()