求助:将单列拆分为Allowance与Deduction两列的SQL查询问题
解决SQL转置Allowance和Deduction列的问题
咱们先唠唠你当前SQL为啥会出问题:你的外层查询加了WHERE BASECODE = 2,这意味着只取了扣款类型的记录,然后子查询里要找同ID且是补贴类型的记录——但这些ID本身就是扣款的,自然找不到匹配的,所以Allowance列全是NULL就不奇怪啦。
下面给你几个实用的解决方案,按需选就行:
方案一:用CASE WHEN条件判断(最简洁高效)
这是处理这类行列转置最常用的方式,直接通过条件筛选对应列的值:
SELECT -- 筛选BASECODE=1的记录作为Allowance列 MAX(CASE WHEN BASECODE = 1 THEN FullName END) AS Allowance, -- 筛选BASECODE=2的记录作为Deduction列 MAX(CASE WHEN BASECODE = 2 THEN FullName END) AS Deduction FROM [AppCNF].[tbl_AllowanceOrBenefitType] -- 如果你的补贴和扣款是按某个类别分组对应的(比如员工ID、类别ID),在这里加上GROUP BY 对应的分组字段
如果你的表中补贴和扣款是成对出现的(比如每个类别下有一个补贴和一个扣款),加上GROUP BY就能完美匹配对应关系;如果只是要把所有补贴和扣款分别列出来,不需要分组的话,这个写法也能得到聚合后的结果。
方案二:自连接(适合无直接关联的场景)
如果补贴和扣款没有共同的关联ID,只是需要按顺序一一对应展示,那可以用CTE生成行号再连接:
WITH AllowanceList AS ( SELECT FullName, -- 给补贴记录按ID排序生成行号 ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber FROM [AppCNF].[tbl_AllowanceOrBenefitType] WHERE BASECODE = 1 ), DeductionList AS ( SELECT FullName, -- 给扣款记录按ID排序生成行号 ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber FROM [AppCNF].[tbl_AllowanceOrBenefitType] WHERE BASECODE = 2 ) SELECT AL.FullName AS Allowance, DL.FullName AS Deduction FROM AllowanceList AL -- 全连接保证补贴和扣款数量不一致时也能显示所有记录 FULL JOIN DeductionList DL ON AL.RowNumber = DL.RowNumber;
这种方式不管补贴和扣款数量是否相等,都能完整展示所有条目。
方案三:修正你原来的子查询写法(不推荐,仅作参考)
如果一定要沿用子查询的思路,得去掉外层的WHERE BASECODE=2,改成对每条记录分别查询对应类型的内容:
SELECT (SELECT FullName FROM [AppCNF].[tbl_AllowanceOrBenefitType] INNER_TBL WHERE INNER_TBL.BASECODE = 1 AND INNER_TBL.ID = OUTER_TBL.ID) AS Allowance, (SELECT FullName FROM [AppCNF].[tbl_AllowanceOrBenefitType] INNER_TBL WHERE INNER_TBL.BASECODE = 2 AND INNER_TBL.ID = OUTER_TBL.ID) AS Deduction FROM [AppCNF].[tbl_AllowanceOrBenefitType] OUTER_TBL -- 去重避免重复记录 GROUP BY OUTER_TBL.ID;
不过这种写法效率较低,不如CASE WHEN简洁,只推荐用来理解问题所在。
内容的提问来源于stack exchange,提问作者Doonie Darkoo
相关产品推荐
相关产品推荐

