Это вообще не иерархический запрос: вы просто хотите разделить каждую входную строку на две выходные строки и применить небольшую логику.
Простой способ выполнить разбиение - CROSS JOIN
ваша таблицак источнику строк, который имеет ровно две строки.
Например,
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 |
+----------+--------+--------+--------------+