You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将按合同、服务类型分组的求和结果转为单合同单行多列形式?

实现行转列(Pivot)的解决方案

这是典型的行转列需求,我们可以用条件聚合的方式来实现,这种方法几乎在所有SQL数据库中都通用,而且后续新增服务类型时也能轻松扩展。

优化后的查询语句

先给你直接能用的SQL代码,我去掉了原查询里没用到的addresses关联,简化了逻辑:

SELECT 
    c.id,
    SUM(CASE WHEN s.servicetype_id = 1 THEN cs.price ELSE 0 END) AS total_service_type_1,
    SUM(CASE WHEN s.servicetype_id = 2 THEN cs.price ELSE 0 END) AS total_service_type_2,
    SUM(CASE WHEN s.servicetype_id = 3 THEN cs.price ELSE 0 END) AS total_service_type_3,
    SUM(CASE WHEN s.servicetype_id = 4 THEN cs.price ELSE 0 END) AS total_service_type_4
FROM contracts c
LEFT JOIN contracts_services cs ON cs.contract_id = c.id
LEFT JOIN services s ON s.id = cs.service_id
GROUP BY c.id
ORDER BY c.id;

关键逻辑解释

  1. 条件聚合核心:
    每个SUM(CASE...)语句对应一个服务类型的总和列。当s.servicetype_id匹配目标类型时,取对应的cs.price值,否则取0(如果希望没有对应服务时显示NULL,可以去掉ELSE 0)。通过SUM()把同一合同下该类型的所有价格加总。

  2. 分组调整:
    原查询是按c.id和s.servicetype_id分组,所以每个合同每个服务类型会生成一行。现在我们只按c.id分组,就能让每个合同只返回一行,所有服务类型的总和作为不同列展示。

  3. 兼容性与扩展性:
    这种条件聚合的写法兼容MySQL、PostgreSQL、SQLite、SQL Server等绝大多数数据库。后续新增服务类型时,只需要复制一行SUM(CASE...)语句,修改对应的servicetype_id和列名即可。

可选:特定数据库的PIVOT语法

如果你的数据库支持PIVOT语法(比如SQL Server、Oracle),也可以用更简洁的写法,比如SQL Server版本:

SELECT 
    id,
    [1] AS total_service_type_1,
    [2] AS total_service_type_2,
    [3] AS total_service_type_3,
    [4] AS total_service_type_4
FROM (
    SELECT c.id, s.servicetype_id, cs.price
    FROM contracts c
    LEFT JOIN contracts_services cs ON cs.contract_id = c.id
    LEFT JOIN services s ON s.id = cs.service_id
) AS SourceTable
PIVOT (
    SUM(price)
    FOR servicetype_id IN ([1], [2], [3], [4])
) AS PivotTable
ORDER BY id;

不过这种写法的兼容性不如条件聚合,所以更推荐第一种通用方案。

内容的提问来源于stack exchange,提问作者Alex Adm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:02:58