寻求CTE技术帮助:实现按子类别展示记录表头名称
解决类别-子类别行转列的CTE实现方案
看起来你现在的SQL只是实现了类别名称仅在组内第一行显示,但没达到「把子类别描述作为表头(列名)」的需求。我来帮你调整成符合预期的方案,核心是用CTE配合动态行转列来实现——因为子类别数量可能不固定,动态SQL能适配不同的子类别情况。
步骤1:明确需求逻辑
先对齐下你要的效果:
- 每个主类别单独占一行
- 每个子类别作为单独的列,列名就是子类别
SubDescription的内容 - 列值对应子类别的
IsOMExceptionRequired/IsAMB/IsARS属性(这里默认用IsOMExceptionRequired的YES/N/A格式,你可以按需替换)
步骤2:动态行转列的CTE实现方案
先保留你原来的临时表创建逻辑,再用CTE整理数据,最后通过动态SQL完成行转列:
-- 保留你原有的临时表创建与数据插入逻辑 DROP TABLE IF EXISTS #temp CREATE TABLE #temp ( [Description] VARCHAR(100), SubDescription VARCHAR(100), IsOMExceptionRequired bit, IsAMB bit, IsARS bit, escalationtypeid int, CategorySortOrder int, SubcategorySortorder int ); INSERT INTO #temp ([Description], SubDescription, IsOMExceptionRequired ,IsAMB,IsARS,escalationtypeid,CategorySortOrder,SubcategorySortorder) SELECT C.Description, s.Description, S.IsOMExceptionRequired, s.IsAMB, s.IsARS, CEM.escalationtypeid, c.SortOrder, s.SortOrder FROM category C INNER JOIN SubCategory S on C.CategoryID =S.CategoryID INNER JOIN CategoryEscalationTypeMap CEM on CEM.CategoryID= C.CategoryID WHERE CEM.escalationtypeid=3 AND CEM.IsActive =1 AND C.IsActive=1 AND S.IsActive=1 ORDER BY CEM.escalationtypeid, C.sortorder,S.sortorder; -- 定义变量存储动态列名和SQL语句 DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX); -- 用CTE统一整理基础数据,预处理属性格式 WITH CategorySubData AS ( SELECT [Description] AS CategoryName, SubDescription, -- 把布尔值转成你需要的YES/N/A格式 CASE WHEN IsOMExceptionRequired = 1 THEN 'YES' ELSE 'N/A' END AS OMExceptionStatus, IsAMB, IsARS, escalationtypeid, CategorySortOrder, SubcategorySortorder FROM #temp ) -- 自动生成所有子类别对应的列名(适配SQL Server 2017+) SELECT @cols = STRING_AGG(QUOTENAME(SubDescription), ', ') FROM (SELECT DISTINCT SubDescription FROM CategorySubData) AS Subs; -- 拼接动态行转列SQL SET @sql = N' SELECT CategoryName, escalationtypeid, CategorySortOrder, ' + @cols + N' FROM ( SELECT CategoryName, SubDescription, OMExceptionStatus, -- 要展示IsAMB/IsARS的话,直接替换成对应字段即可 escalationtypeid, CategorySortOrder FROM CategorySubData ) AS SourceData PIVOT ( MAX(OMExceptionStatus) -- 因为每个类别+子类别是唯一组合,MAX不影响原始值 FOR SubDescription IN (' + @cols + N') ) AS PivotData ORDER BY CategorySortOrder, escalationtypeid; '; -- 执行动态SQL EXEC sp_executesql @sql;
关键细节说明
- CTE的作用:
CategorySubDataCTE用来统一预处理数据,比如把布尔类型的属性转换成你需要的文本格式,避免后续重复处理。 - 动态列生成:用
STRING_AGG自动收集所有唯一的子类别名称,转成带引号的列名,避免列名包含特殊字符导致的语法错误。 - PIVOT函数:核心是把纵向的子类别记录转成横向的列,用
MAX聚合是因为每个主类别+子类别是唯一组合,聚合函数不会改变原始值。 - 灵活适配:如果需要展示
IsAMB或IsARS,只需要把OMExceptionStatus替换成对应的字段即可。
子类别数量固定的静态方案(可选)
如果你的子类别数量是固定的,也可以用静态PIVOT+CTE实现,不用动态SQL:
WITH CategorySubData AS ( SELECT [Description] AS CategoryName, SubDescription, CASE WHEN IsOMExceptionRequired = 1 THEN 'YES' ELSE 'N/A' END AS OMExceptionStatus, escalationtypeid, CategorySortOrder FROM #temp ) SELECT CategoryName, escalationtypeid, CategorySortOrder, [子类别A], [子类别B], [子类别C] -- 替换成你的实际子类别名称 FROM CategorySubData PIVOT ( MAX(OMExceptionStatus) FOR SubDescription IN ([子类别A], [子类别B], [子类别C]) ) AS PivotData ORDER BY CategorySortOrder;
内容的提问来源于stack exchange,提问作者Revathi
相关产品推荐
相关产品推荐

