首页 > 解决方案 > sql将两列旋转到相同的列值

问题描述

我正在尝试转换数据,并且到目前为止已经成功地完成了它,但现在已经走到了死胡同,并在我的问题上寻求一些帮助。

我的数据中有四列。Cat1(旧类别)、val1(旧值)、cat2(新或当前类别)和 val2(其当前值。

我想要的是对于 cat 1 和 cat 2 的每个组合,val2,对于相应列中的旧类别为负数,对于新类别为正数。

示例数据:

 cat1   cat2   val1   val2
 A      B      10     30
 A      A      5      20
 C      A      33     15
 B      C      23     20
 B      A      14     5
 C      B      18     20
 A      B      14     0

我正在寻找的结果是:

change     A     B    C
AtoB      -30   +30   
AtoC       0          0
BtoA      -5     +5
BtoC             -20  +20
CtoA      +15        -15
CtoB            +20  -20

我已经成功地在 CASE 子句的帮助下使用 pivot&unpivot 创建了一个只考虑其中一个列的表。所以我每行只得到一个值:

select * from (select
cat1
SUM(
    CASE WHEN cat1 = A AND cat2 = B THEN val2*-1 ELSE 0 END 
  ) AtoB,
SUM(
    CASE WHEN cat1 = A AND cat2 = C THEN val2*-1 ELSE 0 END 
  ) AtoC,
SUM(
    CASE WHEN cat1 = B AND cat2 = C THEN val2*-1 ELSE 0 END 
  ) BtoC,
SUM(
    CASE WHEN cat1 = C AND cat2 = B THEN val2*-1 ELSE 0 END 
  ) CtoB,
SUM(
    CASE WHEN cat1 = C AND cat2 = A THEN val2*-1 ELSE 0 END 
  ) CtoA,
SUM(
    CASE WHEN cat1 = B AND cat2 = A THEN val2*-1 ELSE 0 END 
  ) BtoA
 FROM table
  group by cat1,cat2)
  unpivot (
  value for cat in 
 (AtoB,AtoC,BtoC,CtoB,CtoA,BtoA)) up
pivot (
sum(value) for cat1 in ('A','B','C')

这里的问题是我只能在 cat1 上获得值,而不是在 cat2 上,尽管它们共享值。我能想到的一个解决方案是创建一些复杂的连接,或者保存这个表,然后在每一行上做一个新的 CASE 子句来复制值乘以 -1,但是感觉这两个解决方案都不是很好,而且我缺少一些更好的解决方案。

在 unpivot 子句之后,我最终得到:

cat1     cat   value
A        AtoB   -30
A        AtoC    0
B        Bto    0
B        AtoB   0
...      ...    ...

PIVOT 语句转换为

cat        A     B    C
AtoB      -30      
AtoC                 
BtoA              -5    
BtoC             -23
CtoA                 -15
CtoB                 -20

标签: sqloracle

解决方案


推荐阅读