SQL :行专列示例

1. 简介

在本教学文档中,我们将详细解释如何使用 SQL 查询将多行数据转为多列显示。我们通过聚合和计算消耗量来构建一个综合结果表。本文将详细解释每个步骤,并附上完整的 SQL 示例代码。

---------------------------------------------------------------------------------------------------------------------------------
附属:行转列的使用场景

 

行转列操作在数据分析和报表生成中常见,以下是几个主要的应用场景:

  1. 报表生成: 将数据按时间或类别展开,更直观地展示业务指标。

    • 示例: 销售报表中,将每个产品的月度销售额转置为列展示。
  2. 数据透视: 汇总数据时,将维度细节转为列数据,方便深入分析。

    • 示例: 广告支出按季度分渠道展示,观察总支出变化。
  3. 时间序列分析: 将不同时间点的数据展示在一行中,便于趋势分析。

    • 示例: 产品年度销售数据转置为按年份展示,查看销售趋势。
  4. 比较分析: 不同类别或时间段的数据对齐在同一行,便于直接对比。

    • 示例: 各地区销售数据转为列展示,比较不同地区的销售表现。
  5. 业务指标监控: 将关键业务指标按时间展开,便于管理层监控和分析。

    • 示例: 各部门月度绩效指标按部门展示,一目了然。
       

总结

行转列简化了数据展示,提升了数据分析的效率,在报表生成、数据透视、趋势分析和比较分析等场景中尤为实用。

---------------------------------------------------------------------------------------------------------------------------------

我们将模拟以下三个表:

  • china_gas_supply:

    • resource_name: VARCHAR, 资源名称
    • plan_supply_num: INT, 计划供应量
    • YEAR: VARCHAR, 年份
    • project_id: VARCHAR, 项目ID
    • analysis_id: VARCHAR, 分析ID
    • is_deleted: TINYINT, 是否删除标志
  • import_pipe_gas_supply:

    • resource_name: VARCHAR, 资源名称
    • plan_supply_num: INT, 计划供应量
    • YEAR: VARCHAR, 年份
    • project_id: VARCHAR, 项目ID
    • analysis_id: VARCHAR, 分析ID
    • is_deleted: TINYINT, 是否删除标志
  • lng_gas_supply:

    • resource_name: VARCHAR, 资源名称
    • plan_supply_num: INT, 计划供应量
    • YEAR: VARCHAR, 年份
    • project_id: VARCHAR, 项目ID
    • analysis_id: VARCHAR, 分析ID
    • is_deleted: TINYINT, 是否删除标志

3. SQL 查询

下面的 SQL 查询将实现以下目标:

  1. 汇总三个表中的天然气供应计划数据。
  2. 按年计算每种资源的总供应量。
  3. 计算所有资源的年度总供应量和消耗量。
  4. 将结果转置为列格式,方便展示。
     
WITH aggregated AS (
    SELECT
        resource_name,
        COALESCE(SUM(CASE WHEN YEAR = '2023' THEN plan_supply_num ELSE 0 END), 0) AS "2023",
        COALESCE(SUM(CASE WHEN YEAR = '2024' THEN plan_supply_num ELSE 0 END), 0) AS "2024",
        COALESCE(SUM(CASE WHEN YEAR = '2025' THEN plan_supply_num ELSE 0 END), 0) AS "2025",
        COALESCE(SUM(CASE WHEN YEAR = '2026' THEN plan_supply_num ELSE 0 END), 0) AS "2026",
        COALESCE(SUM(CASE WHEN YEAR = '2027' THEN plan_supply_num ELSE 0 END), 0) AS "2027",
        COALESCE(SUM(CASE WHEN YEAR = '2028' THEN plan_supply_num ELSE 0 END), 0) AS "2028",
        COALESCE(SUM(CASE WHEN YEAR = '2029' THEN plan_supply_num ELSE 0 END), 0) AS "2029" 
    FROM
    (
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            china_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
        UNION ALL
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            import_pipe_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
        UNION ALL
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            lng_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
    ) AS combined 
    GROUP BY
        resource_name 
),
totals AS (
    SELECT
        COALESCE(SUM("2023"), 0) AS "2023",
        COALESCE(SUM("2024"), 0) AS "2024",
        COALESCE(SUM("2025"), 0) AS "2025",
        COALESCE(SUM("2026"), 0) AS "2026",
        COALESCE(SUM("2027"), 0) AS "2027",
        COALESCE(SUM("2028"), 0) AS "2028",
        COALESCE(SUM("2029"), 0) AS "2029" 
    FROM
        aggregated 
),
consumption AS (
    SELECT
        resource_name,
        COALESCE((SELECT "2023" FROM totals) - "2023", 0) AS "2023",
        COALESCE((SELECT "2024" FROM totals) - "2024", 0) AS "2024",
        COALESCE((SELECT "2025" FROM totals) - "2025", 0) AS "2025",
        COALESCE((SELECT "2026" FROM totals) - "2026", 0) AS "2026",
        COALESCE((SELECT "2027" FROM totals) - "2027", 0) AS "2027",
        COALESCE((SELECT "2028" FROM totals) - "2028", 0) AS "2028",
        COALESCE((SELECT "2029" FROM totals) - "2029", 0) AS "2029" 
    FROM
        aggregated 
),
combined_results AS (
    SELECT
        resource_name,
        "2023",
        "2024",
        "2025",
        "2026",
        "2027",
        "2028",
        "2029",
        1 AS order_priority 
    FROM
        aggregated
    UNION ALL
    SELECT
        '合计' AS resource_name,
        COALESCE(SUM("2023"), 0),
        COALESCE(SUM("2024"), 0),
        COALESCE(SUM("2025"), 0),
        COALESCE(SUM("2026"), 0),
        COALESCE(SUM("2027"), 0),
        COALESCE(SUM("2028"), 0),
        COALESCE(SUM("2029"), 0),
        2 AS order_priority 
    FROM
        aggregated
    UNION ALL
    SELECT
        '消费量' AS resource_name,
        COALESCE(SUM("2023"), 0),
        COALESCE(SUM("2024"), 0),
        COALESCE(SUM("2025"), 0),
        COALESCE(SUM("2026"), 0),
        COALESCE(SUM("2027"), 0),
        COALESCE(SUM("2028"), 0),
        COALESCE(SUM("2029"), 0),
        3 AS order_priority 
    FROM
        consumption 
) 
SELECT
    resource_name,
    "2023",
    "2024",
    "2025",
    "2026",
    "2027",
    "2028",
    "2029" 
FROM
    combined_results 
ORDER BY
    order_priority;

4. SQL 代码解析

4.1. 聚合数据 (aggregated CTE)

aggregated CTE 首先从三个供应表中提取数据,通过 UNION ALL 将它们合并为一个临时表。接着,按 resource_name 对每年数据进行分组聚合,计算每个资源的年计划供应量。
 

WITH aggregated AS (
    SELECT
        resource_name,
        COALESCE(SUM(CASE WHEN YEAR = '2023' THEN plan_supply_num ELSE 0 END), 0) AS "2023",
        COALESCE(SUM(CASE WHEN YEAR = '2024' THEN plan_supply_num ELSE 0 END), 0) AS "2024",
        -- 其他年份同理
    FROM
    (
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            china_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
        UNION ALL
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            import_pipe_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
        UNION ALL
       ```sql
        SELECT
            resource_name,
            plan_supply_num,
            YEAR 
        FROM
            lng_gas_supply
        WHERE
            project_id = '19c32eaa73ca4732bccfdc4c9ff74373' 
            AND analysis_id = 'ce7f2fbb-7db6-4380-899f-e7ec18ac92f6' 
            AND is_deleted = 0
    ) AS combined 
    GROUP BY
        resource_name 
)

上述 SQL 代码片段实现了以下操作:

  • china_gas_supplyimport_pipe_gas_supplylng_gas_supply 三个表中获取数据。
  • 通过 UNION ALL 合并这些表的记录。
  • 使用 COALESCECASE 语句对每一年的数据进行汇总。
  • 最终根据 resource_name 对数据进行分组,以便在后续步骤中转置数据。

4.2. 计算年度总计 (totals CTE)

接下来,通过 totals CTE 计算所有资源的年度总计。
 

totals AS (
    SELECT
        COALESCE(SUM("2023"), 0) AS "2023",
        COALESCE(SUM("2024"), 0) AS "2024",
        COALESCE(SUM("2025"), 0) AS "2025",
        COALESCE(SUM("2026"), 0) AS "2026",
        COALESCE(SUM("2027"), 0) AS "2027",
        COALESCE(SUM("2028"), 0) AS "2028",
        COALESCE(SUM("2029"), 0) AS "2029" 
    FROM
        aggregated 
)

这里,我们从 aggregated CTE 中提取每年的数据,并计算所有资源的年总供应量。

 

4.3. 计算消耗量 (consumption CTE)

consumption CTE 中,我们计算每种资源在每年的消耗量,即年度总量减去该资源的年度供应量。

consumption AS (
    SELECT
        resource_name,
        COALESCE((SELECT "2023" FROM totals) - "2023", 0) AS "2023",
        COALESCE((SELECT "2024" FROM totals) - "2024", 0) AS "2024",
        COALESCE((SELECT "2025" FROM totals) - "2025", 0) AS "2025",
        COALESCE((SELECT "2026" FROM totals) - "2026", 0) AS "2026",
        COALESCE((SELECT "2027" FROM totals) - "2027", 0) AS "2027",
        COALESCE((SELECT "2028" FROM totals) - "2028", 0) AS "2028",
        COALESCE((SELECT "2029" FROM totals) - "2029", 0) AS "2029" 
    FROM
        aggregated 
)

这个 CTE 从 aggregated 中提取资源的年度供应数据,并使用 totals 中的年度总计数据来计算消耗量。

 

4.4. 合并结果并排序 (combined_results CTE)

combined_results CTE 中,我们将前面的结果合并,并按优先级排序,以生成最终结果。
 

combined_results AS (
    SELECT
        resource_name,
        "2023",
        "2024",
        "2025",
        "2026",
        "2027",
        "2028",
        "2029",
        1 AS order_priority 
    FROM
        aggregated
    UNION ALL
    SELECT
        '合计' AS resource_name,
        COALESCE(SUM("2023"), 0),
        COALESCE(SUM("2024"), 0),
        COALESCE(SUM("2025"), 0),
        COALESCE(SUM("2026"), 0),
        COALESCE(SUM("2027"), 0),
        COALESCE(SUM("2028"), 0),
        COALESCE(SUM("2029"), 0),
        2 AS order_priority 
    FROM
        aggregated
    UNION ALL
    SELECT
        '消费量' AS resource_name,
        COALESCE(SUM("2023"), 0),
        COALESCE(SUM("2024"), 0),
        COALESCE(SUM("2025"), 0),
        COALESCE(SUM("2026"), 0),
        COALESCE(SUM("2027"), 0),
        COALESCE(SUM("2028"), 0),
        COALESCE(SUM("2029"), 0),
        3 AS order_priority 
    FROM
        consumption 
)

这里,我们将每个资源的供应数据、合计数据和消耗数据汇总到一起,并根据 order_priority 设置的优先级进行排序。

 

4.5. 最终查询结果

最终,我们从 combined_results 中提取数据并按优先级排序:
 

SELECT
    resource_name,
    "2023",
    "2024",
    "2025",
    "2026",
    "2027",
    "2028",
    "2029" 
FROM
    combined_results 
ORDER BY
    order_priority;

5. 示例数据和输出

  • china_gas_supply:

    resource_nameplan_supply_numYEARproject_idanalysis_idis_deleted
    资源A1002023proj_123analy_4560
    资源B2002023proj_123analy_4560
  • import_pipe_gas_supply:

    resource_nameplan_supply_numYEARproject_idanalysis_idis_deleted
    资源A1502024proj_123analy_4560
    资源C3002024proj_123analy_4560
  • lng_gas_supply:

    resource_nameplan_supply_numYEARproject_idanalysis_idis_deleted
    资源B2502025proj_123analy_4560

运行上述 SQL 查询后,输出结果将类似于以下表格

resource_name2023202420252026202720282029
资源A10015000000
资源B20002500000
资源C030000000
合计3004502500000
消费量0000000

6. 总结

通过使用模拟表结构,我们展示了如何使用 SQL 查询来聚合数据、计算合计与消耗量,并将结果转置为多列展示。这种行转列操作在数据分析和报表生成中非常有用,并且 CTE(公共表表达式)在简化复杂查询中的作用尤为突出。

  • 28
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值