Create first table with key and range
create table ta(key_a, start_a, end_a) as
with data as (
select level n from dual
connect by level <= 2
)
select distinct a.n, b.n, c.n
from data a, data b, data c
where b.n <= c.n
Table created.
The second table also has key and range
create table tb(key_b, start_b, end_b) as
select * from ta
Table created.
select * from ta order by 1,2,3
| KEY_A | START_A | END_A | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 2 |
|---|
select * from tb order by 1,2,3
| KEY_B | START_B | END_B | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 2 | 2 | 2 | 2 |
|---|
Classic join
select KEY_A, START_B, END_B, KEY_B, START_A, END_A
from ta, tb
where key_a between start_b and end_b
and key_b between start_a and end_a
order by 1,2,3,4,5,6
| KEY_A | START_B | END_B | KEY_B | START_A | END_A | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
|---|
Prepare MATCH_RECOGNIZE alternative
with data (order_, tbl_id, key_, start_, end_) as (
select start_a, 'TA', key_a, start_a, end_a from ta
union all
select key_b, 'TB', key_b, start_b, end_b from tb
)
select * from data
order by order_, tbl_id
| ORDER_ | TBL_ID | KEY_ | START_ | END_ | 1 | TA | 1 | 1 | 2 | 1 | TA | 1 | 1 | 1 | 1 | TA | 2 | 1 | 1 | 1 | TA | 2 | 1 | 2 | 1 | TB | 1 | 1 | 2 | 1 | TB | 1 | 2 | 2 | 1 | TB | 1 | 1 | 1 | 2 | TA | 1 | 2 | 2 | 2 | TA | 2 | 2 | 2 | 2 | TB | 2 | 2 | 2 | 2 | TB | 2 | 1 | 2 | 2 | TB | 2 | 1 | 1 |
|---|
MATCH_RECOGNIZE: identify the rows to be "joined"
with data (order_, tbl_id, key_, start_, end_) as (
select start_a, 'TA', key_a, start_a, end_a from ta
union all
select key_b, 'TB', key_b, start_b, end_b from tb
)
select *
from data
match_recognize(
order by order_, tbl_id
measures classifier() classifier, match_number() match_number
all rows per match
after match skip to next row
pattern( A ( B | X )+ )
define A as tbl_id = 'TA',
B as tbl_id = 'TB'
and b.key_ <= a.end_
-- because of the ORDER BY, b.key_ must be >= a.start_
and a.key_ between b.start_ and b.end_,
X as order_ <= a.end_
)
| ORDER_ | TBL_ID | CLASSIFIER | MATCH_NUMBER | KEY_ | START_ | END_ | 1 | TA | A | 1 | 1 | 1 | 2 | 1 | TA | X | 1 | 1 | 1 | 1 | 1 | TA | X | 1 | 2 | 1 | 1 | 1 | TA | X | 1 | 2 | 1 | 2 | 1 | TB | B | 1 | 1 | 1 | 2 | 1 | TB | X | 1 | 1 | 2 | 2 | 1 | TB | B | 1 | 1 | 1 | 1 | 2 | TA | X | 1 | 1 | 2 | 2 | 2 | TA | X | 1 | 2 | 2 | 2 | 2 | TB | X | 1 | 2 | 2 | 2 | 2 | TB | B | 1 | 2 | 1 | 2 | 2 | TB | B | 1 | 2 | 1 | 1 | 1 | TA | A | 2 | 1 | 1 | 1 | 1 | TA | X | 2 | 2 | 1 | 1 | 1 | TA | X | 2 | 2 | 1 | 2 | 1 | TB | B | 2 | 1 | 1 | 2 | 1 | TB | X | 2 | 1 | 2 | 2 | 1 | TB | B | 2 | 1 | 1 | 1 | 1 | TA | A | 3 | 2 | 1 | 1 | 1 | TA | X | 3 | 2 | 1 | 2 | 1 | TB | B | 3 | 1 | 1 | 2 | 1 | TB | B | 3 | 1 | 2 | 2 | 1 | TB | X | 3 | 1 | 1 | 1 | 1 | TA | A | 4 | 2 | 1 | 2 | 1 | TB | B | 4 | 1 | 1 | 2 | 1 | TB | B | 4 | 1 | 2 | 2 | 1 | TB | X | 4 | 1 | 1 | 1 | 2 | TA | X | 4 | 1 | 2 | 2 | 2 | TA | X | 4 | 2 | 2 | 2 | 2 | TB | B | 4 | 2 | 2 | 2 | 2 | TB | B | 4 | 2 | 1 | 2 | 2 | TB | X | 4 | 2 | 1 | 1 | 2 | TA | A | 5 | 1 | 2 | 2 | 2 | TA | X | 5 | 2 | 2 | 2 | 2 | TB | X | 5 | 2 | 2 | 2 | 2 | TB | B | 5 | 2 | 1 | 2 | 2 | TB | B | 5 | 2 | 1 | 1 | 2 | TA | A | 6 | 2 | 2 | 2 | 2 | TB | B | 6 | 2 | 2 | 2 | 2 | TB | B | 6 | 2 | 1 | 2 | 2 | TB | X | 6 | 2 | 1 | 1 |
|---|
MATCH_RECOGNIZE: "join" the A and B rows
with data (order_, tbl_id, key_, start_, end_) as (
select start_a, 'TA', key_a, start_a, end_a from ta
union all
select key_b, 'TB', key_b, start_b, end_b from tb
)
select KEY_A, start_ as START_B, end_ as END_B,
key_ as KEY_B, START_A, END_A
from data
match_recognize(
order by order_, tbl_id
measures a.key_ as key_a, a.start_ as start_a, a.end_ as end_a
all rows per match
after match skip to next row
pattern( {-A-} ( B | {-X-} )+ )
define A as tbl_id = 'TA',
B as tbl_id = 'TB'
and b.key_ <= a.end_
-- because of the ORDER BY, b.key_ must be >= a.start_
and a.key_ between b.start_ and b.end_,
X as order_ <= a.end_
)
| KEY_A | START_B | END_B | KEY_B | START_A | END_A | 1 | 1 | 2 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 |
|---|