SQL 如何将组内多字段同时行转列 *

有数据库表FACTTABLE,数据如下所示:

ID

TYPE

VALUE

CURRENCY

ABC

TOT_AMT

3

5.7702

ABC

AMT_AVAL

1

1.9234

ABC

DRWN_AMT

2

3.8468

ABC

MTD_DRWN

2

3.8468

DEF

TOT_AMT

3

5.7702

DEF

AMT_AVAL

1

1.9234

DEF

DRWN_AMT

2

3.8468

DEF

MTD_DRWN

2

3.8468

需要按ID分组,组内多字段同时行转列,结果如下所示:

ID

AMT_AVAL

AMT_AVAL1

DRWN_AMT

DRWN_AMT1

MTD_DRWN

MTD_DRWN1

TOT_AMT

TOT_AMT1

ABC

1

1.9234

2

3.8468

2

3.8468

3

5.7702

DEF

1

1.9234

2

3.8468

2

3.8468

3

5.7702

VALUECURRENCY分别对应"TYPE""TYPE"1列,变成相应的行值

SQL ServerSQL

WITH CTE AS

(

  SELECT UP.ID,

         UP.TYPE + '_' + LEFT(UP.VALUETYPE, 4AS NEW_CODE,

         UP.VALUE1

  FROM FACTTABLE

  UNPIVOT (VALUE1 FOR VALUETYPE IN (VALUE, CURRENCY)) UP

)

SELECT P.ID,

       P.TOT_AMT_CURR                       AS TOT_AMT,

       P.TOT_AMT_VALU                        AS TOT_AMT1,

       P.AMT_AVAL_CURR                     AS AMT_AVAL,

       P.AMT_AVAL_VALU                      AS AMT_AVAL1,

       P.DRWN_AMT_CURR                   AS DRWN_AMT,

       P.DRWN_AMT_VALU                   AS DRWN_AMT1,

       P.MTD_DRWN_CURR                   AS MTD_DRWN,

       P.MTD_DRWN_VALU                   AS MTD_DRWN1

FROM CTE

PIVOT (MAX(VALUE1) FOR NEW_CODE IN ([TOT_AMT_CURR], [TOT_AMT_VALU],

                                   [AMT_AVAL_CURR], [AMT_AVAL_VALU],

                                   [DRWN_AMT_CURR], [DRWN_AMT_VALU],

                                   [MTD_DRWN_CURR], [MTD_DRWN_VALU])) P

用自然思维去解这道题并不难,只需要将VALUECURRENCY这两列先转成行,比如TYPETOT_AMTVALUE对应TOT_AMTCURRENCY对应TOT_AMT1依此类推,然后再直接行转列即可。SQL不支持动态行列转换,当列数较少且固定时,勉强可以应付。但是当列数较多时,因为转换过程中需要枚举出所有列,所以写起来很费劲,写出的SQL也非常臃肿。如果是动态列,那就需要更复杂的办法来解了。

用开源集算器的SPL就很容易写:


A

1

=connect("mssql")

2

=A1.query@x("SELECT * FROM FACTTABLE")

3

=A2.news([VALUE,CURRENCY];ID,TYPE,~:VALUE).run(if(#%2==0,TYPE=TYPE/"1"))

4

=A3.pivot(ID;TYPE,VALUE)

SPL是专业的数据计算引擎,基于有序集合设计,提供了完善的集合运算,相当于JavaSQL优势的结合,很容易处理各种行列转换问题。

问答搜集

https://stackoverflow.com/questions/64132722/pivot-operator-on-two-columns