# 安全扫描实例明细分析 (PrestoSQL)

## Prompt
任务目标：从安全扫描 span 信息和资源分配信息关联产出安全扫描实例运行明细表。

输入：
- internal_platform_db.t_security_scan_span_prestosql_001
- internal_platform_db.t_security_resource_info_prestosql_001

处理规则：
- 两表关联查询，关联条件需基于表结构确定
- 具体过滤条件和字段选择需基于表结构确定

输出要求：
- 输出表：internal_platform_db.t_security_scan_instance_detail_cand_prestosql_001
- 输出字段需基于目标表结构确定

写入要求：
- 写入目标表

请将最终 Presto/Trino SQL 写入 result.sql 并执行。

## Reference Solution
INSERT INTO internal_platform_db.t_security_scan_instance_detail_prestosql_001
WITH base_trace AS (
    SELECT trace_id
    FROM internal_platform_db.t_security_scan_span_prestosql_001
    WHERE databus_imp_date >= '2026060600'
      AND databus_imp_date <= '2026060800'
      AND span_name IN ('scan.completed', 'scan.failed')
    GROUP BY trace_id
    HAVING
        COUNT(CASE WHEN span_name = 'scan.failed' THEN 1 END) > 0
        AND
        COUNT(CASE WHEN span_name = 'scan.completed' THEN 1 END) = 0
),
combined_spans AS (
    SELECT
        trace_id,
        span_name,
        start_time,
        end_time,
        security_project_id,
        security_task_id,
        scan_type,
        status_code
    FROM internal_platform_db.t_security_scan_span_prestosql_001
    WHERE databus_imp_date >= '2026060600'
      AND databus_imp_date <= '2026060800'
      AND trace_id IN (SELECT trace_id FROM base_trace)
      AND span_name IN ('scan.failed', 'scan.start', 'scan.execute', 'scan.cleanup', 'resource.allocate')

    UNION ALL

    SELECT
        trace_id,
        'scan.completed' AS span_name,
        MAX(CASE WHEN span_name = 'scan.start' THEN start_time END) AS start_time,
        MAX(CASE WHEN span_name = 'scan.failed' THEN end_time END) AS end_time,
        MAX(CASE WHEN span_name = 'scan.failed' THEN security_project_id END) AS security_project_id,
        MAX(CASE WHEN span_name = 'scan.failed' THEN security_task_id END) AS security_task_id,
        MAX(CASE WHEN span_name = 'scan.failed' THEN scan_type END) AS scan_type,
        2 AS status_code
    FROM internal_platform_db.t_security_scan_span_prestosql_001
    WHERE databus_imp_date >= '2026060600'
      AND databus_imp_date <= '2026060800'
      AND trace_id IN (SELECT trace_id FROM base_trace)
      AND span_name IN ('scan.start', 'scan.failed')
    GROUP BY trace_id
),
base_data_time_fixed AS (
    SELECT
        trace_id,
        span_name,
        CASE
            WHEN span_name = 'scan.failed'
                THEN MIN(CASE WHEN span_name IN ('scan.execute', 'scan.failed') THEN start_time END)
                        OVER(PARTITION BY trace_id)
                ELSE start_time
        END AS start_time,
        end_time,
        security_project_id,
        security_task_id,
        scan_type,
        status_code
    FROM combined_spans
),
base_data AS (
    SELECT
        trace_id,
        span_name,
        start_time,
        end_time,
        security_project_id,
        security_task_id,
        scan_type,
        status_code,
        from_unixtime(CAST(start_time AS BIGINT) / 1000) AS start_date,
        from_unixtime(CAST(end_time AS BIGINT) / 1000) AS end_date,
        date_diff('day', from_unixtime(CAST(start_time AS BIGINT) / 1000), from_unixtime(CAST(end_time AS BIGINT) / 1000)) AS diff_days,
        CAST(CAST(start_time AS BIGINT) / 86400000 AS BIGINT) * 86400000 AS start_day_midnight_ms
    FROM base_data_time_fixed
),
pos_series AS (
    SELECT 0 AS pos UNION ALL SELECT 1 AS pos UNION ALL SELECT 2 AS pos UNION ALL SELECT 3 AS pos
),
daily_split_spans AS (
    SELECT
        b.trace_id,
        b.span_name,
        b.security_project_id,
        b.security_task_id,
        b.scan_type,
        b.status_code,
        b.start_date,
        b.end_date,
        b.diff_days,
        date_add('day', s.pos, b.start_date) AS calc_date,
        CASE WHEN s.pos = 0 THEN b.start_time
             ELSE CAST(b.start_day_midnight_ms + s.pos * 86400000 AS VARCHAR)
        END AS start_time,
        CASE WHEN s.pos = b.diff_days THEN b.end_time
             ELSE CAST(b.start_day_midnight_ms + (s.pos + 1) * 86400000 - 1 AS VARCHAR)
        END AS end_time,
        b.start_time AS span_start_time,
        b.end_time AS span_end_time
    FROM base_data b
    INNER JOIN pos_series s ON s.pos <= b.diff_days
),
trace_time_metrics AS (
    SELECT
        t.trace_id,
        t.calc_date,
        MAX(t.security_project_id) AS security_project_id,
        MAX(t.security_task_id) AS security_task_id,
        MAX(t.scan_type) AS scan_type,
        MAX(MAX(CASE WHEN t.span_name = 'scan.completed' THEN t.status_code END)) OVER(PARTITION BY t.trace_id) AS status_code,
        CAST(ROUND((MAX(CASE WHEN t.span_name = 'scan.execute' THEN CAST(t.end_time AS BIGINT) END) -
                    MIN(CASE WHEN t.span_name = 'scan.execute' THEN CAST(t.start_time AS BIGINT) END)) / 1000.0) AS INT) AS scan_run_time,
        CAST(ROUND((MAX(CASE WHEN t.span_name IN ('scan.execute', 'scan.cleanup') THEN CAST(t.end_time AS BIGINT) END) -
                    MIN(CASE WHEN t.span_name IN ('scan.execute', 'scan.cleanup') THEN CAST(t.start_time AS BIGINT) END)) / 1000.0) AS INT) AS code_run_time,
        CAST(ROUND((MAX(CASE WHEN t.span_name = 'resource.allocate' THEN CAST(t.end_time AS BIGINT) END) -
                    MIN(CASE WHEN t.span_name = 'resource.allocate' THEN CAST(t.start_time AS BIGINT) END)) / 1000.0) AS INT) AS resource_wait_time
    FROM daily_split_spans t
    GROUP BY t.trace_id, t.calc_date
)
SELECT
    date_format(t1.calc_date, '%Y-%m-%d') AS p_date,
    t1.trace_id,
    t1.security_project_id,
    t1.security_task_id,
    t1.scan_type,
    t1.status_code,
    t1.scan_run_time,
    t1.code_run_time,
    t1.resource_wait_time,
    t2.resource_id,
    CAST(t2.is_dedicated AS BOOLEAN) AS is_dedicated,
    t2.apply_for_cpu_count
FROM trace_time_metrics t1
LEFT JOIN (
    SELECT
        trace_id,
        MAX(resource_id) AS resource_id,
        MAX(is_dedicated) AS is_dedicated,
        MAX(cpu_cores) AS apply_for_cpu_count
    FROM internal_platform_db.t_security_resource_info_prestosql_001
    WHERE databus_imp_date >= '2026060600'
      AND databus_imp_date <= '2026060800'
    GROUP BY trace_id
) t2 ON t1.trace_id = t2.trace_id
;