SQL运用full join连接,decode函数,nvl函数进行列转行
阅读原文时间:2023年09月27日阅读:1

背景说明:
full join连接,decode函数,nvl函数,结合生产背景理解更深刻:

test_A表是现金业主某时间段的收益;test_B表是非现金业主某时间段的收益;对于业主,test_A表与test_B表的业主有交集。

现要求,求某天所有业主的各自收益。

表说明:

test_A是现金业主收益表,test_B是非现金业主收益表。v_member是业主编号,v_date是某时间段,v_mount是收益。

思路整理:①先筛选满足某天'2020-09-24 00:00:00'的数据_ test_A 满足条件V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')的数据, test_B 满足条件V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')的数据._

②将"两个表满足条件的记录"都展示出来
selet * from (满足条件test_A)A full join (满足条件test_B) on A.v_member=A.v_member

③对结果集进行列转行处理
在列转行时,对于空值采用decode,nvl处理。

1、准备测试环境

1、准备测试环境

create table test_A(v_member number,v_date date,v_mount number);
create table test_B(v_member number,v_date date,v_mount number);

insert into test_A
select rownum,to_date(trunc(dbms_random.value(to_number(to_char(sysdate-5,'J')),to_number(to_char(sysdate,'J')))),'J'),floor(dbms_random.value(0,100)) from dual connect by rownum<10;

insert into test_B
select rownum+4,to_date(trunc(dbms_random.value(to_number(to_char(sysdate-5,'J')),to_number(to_char(sysdate,'J')))),'J'),floor(dbms_random.value(0,100)) from dual connect by rownum<10;

test_A收益表,记录展示如下:
select * from test_A;
V_MEMBER V_DATE V_MOUNT


1 2020-09-23 00:00:00 26
2 2020-09-27 00:00:00 87
3 2020-09-25 00:00:00 33
4 2020-09-24 00:00:00 20
5 2020-09-24 00:00:00 70
6 2020-09-23 00:00:00 51
7 2020-09-24 00:00:00 16
8 2020-09-26 00:00:00 65
9 2020-09-23 00:00:00 95

test_B收益表,记录展示如下:
select * from test_B;
V_MEMBER V_DATE V_MOUNT


5 2020-09-24 00:00:00 26
6 2020-09-27 00:00:00 41
7 2020-09-23 00:00:00 35
8 2020-09-25 00:00:00 12
9 2020-09-25 00:00:00 57
10 2020-09-25 00:00:00 10
11 2020-09-24 00:00:00 47
12 2020-09-23 00:00:00 5
13 2020-09-27 00:00:00 18

2、将满足条件的记录展示出来

select A.*,B.* from
(
select * from TEST_A where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)A full JOIN
(
select * from TEST_B where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)B
on A.V_MEMBER=B.V_MEMBER

V_MEMBER V_DATE V_MOUNT V_MEMBER V_DATE V_MOUNT


4 2020-09-24 00:00:00 20 (null) (null) (null)
5 2020-09-24 00:00:00 70 5 2020-09-24 00:00:00 26
7 2020-09-24 00:00:00 16 (null) (null) (null)
(null) (null) (null) 11 2020-09-24 00:00:00 47

说明:用full join将满足条件的记录都展示出来。
满足'2020-09-24 00:00:00'的test_A有业主4,5,7;满足'2020-09-24 00:00:00'的test_B有业主5,11;test_A与test_B两表同时间业主交集:5。

3、将列转成行,展示需要的记录
处理行列转行的思路:V_MEMBER,V_DATE哪个表的值不为null就取它,若同时不为null就取test_A的字段值。V_MOUNT谁的值不为null就取谁的值,若都不为null就取两表的累计值。

①采用decode函数
select decode(A.V_MEMBER,null,B.V_MEMBER,A.V_MEMBER) V_MEMBER,decode(A.V_Date,null,B.V_Date,a.V_Date) V_Date, decode(A.V_MOUNT,null,0,A.V_MOUNT)+decode(B.V_MOUNT,NULL,0,B.V_MOUNT) Amount
from
(
select * from TEST_A where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)A full JOIN
(
select * from TEST_B where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)B
on A.V_MEMBER=B.V_MEMBER

②采用nvl函数
select nvl(A.V_MEMBER,B.V_MEMBER) V_MEMBER,nvl(A.V_Date,B.V_Date) V_Date, nvl(A.V_MOUNT,0)+nvl(B.V_MOUNT,0) Amount
from
(
select * from TEST_A where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)A full JOIN
(
select * from TEST_B where V_DATE=TO_DATE('2020-09-24 00:00:00','YYYY-MM-DD HH24:MI:SS')
)B
on A.V_MEMBER=B.V_MEMBER

/******************查询结果展示******************/
V_MEMBER V_DATE AMOUNT


4 2020-09-24 00:00:00 20
5 2020-09-24 00:00:00 96
7 2020-09-24 00:00:00 16
11 2020-09-24 00:00:00 47

注意:业主5在'2020-09-24 00:00:00'的收益是有test_A与test_B共同贡献的。
至此,所有业主在某天的各自收益已经汇总出来。

其他问题请关注目录:https://www.cnblogs.com/handhead/