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

使用CTE与CASE语句实现行压缩的技术问题

解决SQL查询结果分组压缩(行转列)的问题

嘿,我完全懂你现在的困扰——就是想把同一个人的多个Plan ID合并到一行里,而不是拆成每行只有一个Plan ID的多行数据对吧?我给你分享两种实用的解决办法,应该能完美匹配你的需求。

方法一:条件聚合(通用所有SQL数据库)

这种方法兼容性极强,几乎所有支持SQL的数据库都能使用,核心思路是给每个用户的Plan ID分配序号,再通过条件判断+聚合函数把多行合并成一行。

修改你的CTE,加入行号生成逻辑,再用CASE WHEN结合MAX聚合:

;WITH CTE AS (
    SELECT 
        p.id [Person ID], 
        plan.id [Plan ID],
        -- 给每个Person的Plan ID按顺序编号(1、2、3...),排序规则可按需调整
        ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY plan.id) AS PlanSeq
    FROM 
        -- 这里替换成你原本的表连接逻辑,比如 person p JOIN plan_table plan ON ...
)
SELECT 
    [Person ID],
    MAX(CASE WHEN PlanSeq = 1 THEN [Plan ID] END) AS [Plan ID 1],
    MAX(CASE WHEN PlanSeq = 2 THEN [Plan ID] END) AS [Plan ID 2],
    MAX(CASE WHEN PlanSeq = 3 THEN [Plan ID] END) AS [Plan ID 3]
FROM CTE
GROUP BY [Person ID];

关键逻辑说明:

  • ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY plan.id):按Person ID分组,给每个组内的Plan ID分配唯一序号,ORDER BY可以根据实际需求调整(比如按Plan创建时间排序)。
  • MAX(CASE ...):针对每个序号筛选对应的Plan ID,用MAX聚合是因为同一Person+序号组合只有一个非NULL值,最终会把多行的非NULL值合并到一行的对应列中。

方法二:使用PIVOT(适用于SQL Server、Oracle 11g+等支持PIVOT的数据库)

如果你的数据库支持PIVOT语法,这种写法会更简洁,同样需要先给Plan ID生成序号,再通过PIVOT转成列:

;WITH CTE AS (
    SELECT 
        p.id [Person ID], 
        plan.id [Plan ID],
        -- 生成对应的列名,比如 "Plan ID 1"、"Plan ID 2"
        'Plan ID ' + CAST(ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY plan.id) AS VARCHAR) AS PlanColumn
    FROM 
        -- 替换成你原本的表连接逻辑
)
SELECT 
    [Person ID],
    [Plan ID 1], [Plan ID 2], [Plan ID 3]
FROM CTE
PIVOT (
    MAX([Plan ID])  -- 聚合函数,这里用MAX/MIN都可以
    FOR PlanColumn IN ([Plan ID 1], [Plan ID 2], [Plan ID 3])  -- 指定要转成的列
) AS PivotResult;

注意事项:

  • 如果用户的Plan数量可能超过3个,只需要在SELECT和PIVOT的IN子句中添加对应的列(比如[Plan ID 4])即可。
  • 若某个Person没有对应序号的Plan,对应的列会自动显示为NULL,完全符合你期望的结果格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:17:35