Oracle SQL - 从单行的列组合中导出多行
Oracle SQL - Derive multiple rows from column combination of single row
我在 Oracle SQL DB 上有这种数据:
personId lastEvent currentEvent nextEvent
1 null 1 2
1 1 2 3
1 2 3 4
1 3 4 null
对于像
这样的单行
personId lastEvent currentEvent nextEvent
1 null 1 2
我想提取通过将事件列组合在一起提取的两行并将这两行归类到特定的 currentEvent。例如:
第 1 行
personId lastEvent currentEvent nextEvent
1 null 1 2
结果#1
personId event1 event2 currentEvent
1 null 1 1
1 1 2 1
第 2 行
personId lastEvent currentEvent nextEvent
1 1 2 3
结果#2
personId event1 event2 currentEvent
1 1 2 2
1 2 3 2
等等.....
我知道子句 CONNECT BY 的存在,但我真的无法找出获得这些结果的查询。
这是一种方法。
虽然我没有为此使用分层查询。
create table t(personId int,lastEvent int, currentEvent int, nextEvent int);
insert into t values(1,null,1,2);
insert into t values(1,1,2,3);
insert into t values(1,2,3,4);
insert into t values(1,3,4,null);
select a.personId,case when b.rn=1 then
a.lastEvent
else a.currentEvent
end as event1
,case when b.rn=1 then
a.currentEvent
else a.nextEvent
end as event2
,case when a.nextEvent is not null then
a.currentEvent
end as currentEvent
from t a
join (select rownum as rn from all_objects where rownum<=2) b
on case when a.nextEvent is not null then 2
else 1
end >=b.rn
order by 1,4,3
+----------+--------+--------+--------------+
| PERSONID | EVENT1 | EVENT2 | CURRENTEVENT |
+----------+--------+--------+--------------+
| 1 | - | 1 | 1 |
| 1 | 1 | 2 | 1 |
| 1 | 1 | 2 | 2 |
| 1 | 2 | 3 | 2 |
| 1 | 2 | 3 | 3 |
| 1 | 3 | 4 | 3 |
| 1 | 3 | 4 | - |
+----------+--------+--------+--------------+
这根本不是分层查询:您只想将每个输入行拆分为两个输出行并应用一些逻辑。
执行拆分的一种简单方法是 CROSS JOIN
您的 table 到恰好有两行的行源。
例如,
with input_data ( personId, lastEvent, currentEvent, nextEvent) AS
(
SELECT 1, null, 1, 2 FROM DUAL UNION ALL
SELECT 1, 1, 2, 3 FROM DUAL UNION ALL
SELECT 1, 2, 3, 4 FROM DUAL UNION ALL
SELECT 1, 3, 4, null FROM DUAL )
SELECT personId,
decode(rn, 1, lastEvent, 2, currentEvent) event1,
decode(rn, 1, currentEvent, 2, nextEvent) event2,
currentEvent
from input_data
CROSS JOIN ( SELECT rownum rn FROM DUAL CONNECT BY ROWNUM <= 2 ) r
ORDER BY personId, currentEvent, rn;
+----------+--------+--------+--------------+
| PERSONID | EVENT1 | EVENT2 | CURRENTEVENT |
+----------+--------+--------+--------------+
| 1 | | 1 | 1 |
| 1 | 1 | 2 | 1 |
| 1 | 1 | 2 | 2 |
| 1 | 2 | 3 | 2 |
| 1 | 2 | 3 | 3 |
| 1 | 3 | 4 | 3 |
| 1 | 3 | 4 | 4 |
| 1 | 4 | | 4 |
+----------+--------+--------+--------------+
我在 Oracle SQL DB 上有这种数据:
personId lastEvent currentEvent nextEvent
1 null 1 2
1 1 2 3
1 2 3 4
1 3 4 null
对于像
这样的单行personId lastEvent currentEvent nextEvent
1 null 1 2
我想提取通过将事件列组合在一起提取的两行并将这两行归类到特定的 currentEvent。例如:
第 1 行
personId lastEvent currentEvent nextEvent
1 null 1 2
结果#1
personId event1 event2 currentEvent
1 null 1 1
1 1 2 1
第 2 行
personId lastEvent currentEvent nextEvent
1 1 2 3
结果#2
personId event1 event2 currentEvent
1 1 2 2
1 2 3 2
等等..... 我知道子句 CONNECT BY 的存在,但我真的无法找出获得这些结果的查询。
这是一种方法。
虽然我没有为此使用分层查询。
create table t(personId int,lastEvent int, currentEvent int, nextEvent int);
insert into t values(1,null,1,2);
insert into t values(1,1,2,3);
insert into t values(1,2,3,4);
insert into t values(1,3,4,null);
select a.personId,case when b.rn=1 then
a.lastEvent
else a.currentEvent
end as event1
,case when b.rn=1 then
a.currentEvent
else a.nextEvent
end as event2
,case when a.nextEvent is not null then
a.currentEvent
end as currentEvent
from t a
join (select rownum as rn from all_objects where rownum<=2) b
on case when a.nextEvent is not null then 2
else 1
end >=b.rn
order by 1,4,3
+----------+--------+--------+--------------+
| PERSONID | EVENT1 | EVENT2 | CURRENTEVENT |
+----------+--------+--------+--------------+
| 1 | - | 1 | 1 |
| 1 | 1 | 2 | 1 |
| 1 | 1 | 2 | 2 |
| 1 | 2 | 3 | 2 |
| 1 | 2 | 3 | 3 |
| 1 | 3 | 4 | 3 |
| 1 | 3 | 4 | - |
+----------+--------+--------+--------------+
这根本不是分层查询:您只想将每个输入行拆分为两个输出行并应用一些逻辑。
执行拆分的一种简单方法是 CROSS JOIN
您的 table 到恰好有两行的行源。
例如,
with input_data ( personId, lastEvent, currentEvent, nextEvent) AS
(
SELECT 1, null, 1, 2 FROM DUAL UNION ALL
SELECT 1, 1, 2, 3 FROM DUAL UNION ALL
SELECT 1, 2, 3, 4 FROM DUAL UNION ALL
SELECT 1, 3, 4, null FROM DUAL )
SELECT personId,
decode(rn, 1, lastEvent, 2, currentEvent) event1,
decode(rn, 1, currentEvent, 2, nextEvent) event2,
currentEvent
from input_data
CROSS JOIN ( SELECT rownum rn FROM DUAL CONNECT BY ROWNUM <= 2 ) r
ORDER BY personId, currentEvent, rn;
+----------+--------+--------+--------------+ | PERSONID | EVENT1 | EVENT2 | CURRENTEVENT | +----------+--------+--------+--------------+ | 1 | | 1 | 1 | | 1 | 1 | 2 | 1 | | 1 | 1 | 2 | 2 | | 1 | 2 | 3 | 2 | | 1 | 2 | 3 | 3 | | 1 | 3 | 4 | 3 | | 1 | 3 | 4 | 4 | | 1 | 4 | | 4 | +----------+--------+--------+--------------+