行列互换-高级语法-oracle


我最近在做一个Java web项目,其中某个模块设计需要展示数据表格和图标,如图, 在这里插入图片描述

而数据库中数据存在2张表中(数据版本为oracle 11g):

  • 表1 存储的配置表 ,图示:在这里插入图片描述

  • 表2存储的为数据(数值),图示:在这里插入图片描述

那么我们改如何把表中数据转换为上面我们我们想要展示的数据呢?

通过观察发现:

  1. 目标数据3个单位列对应我们表2中的3个单位id

  2. 目标数据的类别类对应表2中xm2列

  3. 目标数值对应表2中的n1列

  4. 目标数据最后一行数据为dm ‘0306’ ‘0307’ ‘0308’ 的3行之和

分析:

  • 想要实现多行合并一行(对应列相加),并没有太好的办法,但是我们经常做多列合并为一列的操作,对的这里我们先把列(xm2)行转列,把行合并转为列合并(相加),就实现了上面的4
  • 此时查询结果和目标数据完全的行列倒置了,我们需要实现行列互换
  • 首先列转行,既类别列转为行
  • 接下来行转列,把单位行转为列
  • 最后数据排序达到我们需要的数据

先介绍下Oracle相关的基础知识

1、行转列

pivot

语法:

select * from (select 字段 fromwhere 条件) unpivot (聚合函数(字段) for 字段 in (1 别名,2 别名 ))

已上面合并三行为例:

SELECT DWID, GJJS, JS, GJG, ZJG, NVL(CJG, 0) + NVL(WW, 0) + NVL(FW, 0) CJYX
  FROM (SELECT DWID, N1, XM2
           FROM RPT_LDYG_007
          WHERE DWID IN ('10010001', '30200000', '10200000')
                AND NY = '202104'
                AND XM = '03')

PIVOT(MAX(N1)
   FOR XM2 IN('0302' AS GJJS, '0303' AS JS, '0304' AS GJG, '0305' AS ZJG, '0306' AS CJG, '0307' AS WW, '0308' AS FW));

查询结果如图:在这里插入图片描述

2、列转行

unpivot

语法:

select * from (select 字段 fromwhere 条件) unpivot (虚拟字段 for 字段 in (1 别名,2 别名 ))

离目标数据又仅了了一步,想要实现完全的行列倒置,我们先把类别列转为行:

SELECT *  FROM 
(SELECT dwid, gjjs, js, gjg, zjg, nvl(cjg, 0) + nvl(ww, 0) + nvl(fw, 0) cjyx
   FROM (SELECT dwid, n1, xm2
            FROM rpt_ldyg_007
           WHERE dwid IN ('10010001', '30200000', '10200000')
                 AND ny = '202104'
                 AND xm = '03')
         
 pivot(MAX(n1)
    FOR xm2 IN('0302' AS gjjs, '0303' AS js, '0304' AS gjg, '0305' AS zjg, '0306' AS cjg, '0307' AS ww, '0308' AS fw))
) 
unpivot(a FOR lb IN(gjjs, js, gjg, zjg, cjysq

查询结果如图:在这里插入图片描述

3、行列互换

最后一步吧单位行转为列,这样得到我们想要的数据了

SELECT 'zy' LX, LB,
       DECODE(LB, 'GJJS', '高级技师', 'JS', '技师', 'GJG', '高级工', 'ZJG', '中级工', 'CJYX', '初级工及以下') MC, QYT, FGS, GLJ
  FROM (SELECT DWID, GJJS, JS, GJG, ZJG, NVL(CJG, 0) + NVL(WW, 0) + NVL(FW, 0) CJYX
           FROM (SELECT DWID, N1, XM2
                    FROM RPT_LDYG_007
                   WHERE DWID IN ('10010001', '30200000', '10200000')
                     AND NY = '202104'
                     AND XM = '03')
         
         PIVOT(MAX(N1)
            FOR XM2 IN('0302' AS GJJS,
                      '0303' AS JS,
                      '0304' AS GJG,
                      '0305' AS ZJG,
                      '0306' AS CJG,
                      '0307' AS WW,
                      '0308' AS FW))) UNPIVOT(A FOR LB IN(GJJS, JS, GJG, ZJG, CJYX))
PIVOT(MAX(A)
   FOR DWID IN('10010001' AS QYT, '30200000' AS FGS, '10200000' AS GLJ))

查询结果图示:在这里插入图片描述

为什么加上LX这一列呢 ?因为有其他类型的数据需要一起查询为了区分加上的。

最后怎么保证顺序呢? 我们想要的是 高级技师、 技师、高级工、中级工、初级工及以下这样的顺序

当然是通过order by 排序了,完整查询语句:

SELECT 'zy' LX, LB,
       DECODE(LB, 'GJJS', '高级技师', 'JS', '技师', 'GJG', '高级工', 'ZJG', '中级工', 'CJYX', '初级工及以下') MC, QYT, FGS, GLJ
  FROM (SELECT DWID, GJJS, JS, GJG, ZJG, NVL(CJG, 0) + NVL(WW, 0) + NVL(FW, 0) CJYX
           FROM (SELECT DWID, N1, XM2
                    FROM RPT_LDYG_007
                   WHERE DWID IN ('10010001', '30200000', '10200000')
                     AND NY = '202104'
                     AND XM = '03')
         
         PIVOT(MAX(N1)
            FOR XM2 IN('0302' AS GJJS,
                      '0303' AS JS,
                      '0304' AS GJG,
                      '0305' AS ZJG,
                      '0306' AS CJG,
                      '0307' AS WW,
                      '0308' AS FW))) UNPIVOT(A FOR LB IN(GJJS, JS, GJG, ZJG, CJYX))
PIVOT(MAX(A)
   FOR DWID IN('10010001' AS QYT, '30200000' AS FGS, '10200000' AS GLJ))
     order by DECODE(LB, 'GJJS', 1, 'JS',2, 'GJG', 3, 'ZJG', 4, 'CJYX', 5);

查询结果:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值