ENH: IntervalArray/IntervalIndex Range Joins
#### Is your feature request related to a problem?

I'm interested in adding additional options that would modify the behavior of merge, join, and concatenate operations when performed between IntervalArrays or IntervalIndexes.

There has been a fair amount of related discussion in a number of somewhat stale issues. I'd be happy to continue the discussion on one of those if it makes more sense.
* #19480
* #18975
* #22939
* #21998

#### Describe the solution you'd like

I'd like to be able to do merges on joins using Intervals where instead of finding exact matches the overlapping ranges are matched and split up as needed. Suppose we have the following two DataFrames.

``` python
idx_A = pd.IntervalIndex.from_tuples([(1, 4), (4, 6), (8, 9)])
df_A = pd.DataFrame(data={'A':['A1', 'A2', 'A3']}, index=idx_A)

idx_B = pd.IntervalIndex.from_tuples([(2, 3), (3, 5), (5, 10)])
df_B = pd.DataFrame(data={'B':['B1', 'B2', 'B3']}, index=idx_B)
```
<img width="247" alt="Screen Shot 2021-08-13 at 8 57 04 PM" src="https://user-images.githubusercontent.com/1461273/129429809-bfc16df4-8204-4706-9f06-5e9c90b89c90.png">

Currently, an outer join would not match any of the rows at all because it only joins Intervals that are equal.

`df_A.join(df_B, how='outer')`

<img width="255" alt="Screen Shot 2021-08-13 at 9 00 15 PM" src="https://user-images.githubusercontent.com/1461273/129429913-20a00f13-248c-40c6-b21d-d9e37d63a51b.png">

I'm interested in having an option that would change the behavior so that the overlapping portions of the intervals would be aligned. So the result would look like this.

``` python
df_a.join(df_B, how='overlapping') # not at all wedded to that parameter
idx_expected = pd.IntervalIndex.from_tuples([
    (1,2), (2,3), (3,4), (4,5),
    (5,6), (6,9),(9,10)])

df_expected = pd.DataFrame(
    index=idx_expected, data={
        'A': ['A1', 'A1', 'A1', 'A1', 'A2', 'A2', np.nan],
        'B': [np.nan, 'B1', 'B2', 'B2', 'B3', 'B3', 'B3']
    }
    
)
```
<img width="136" alt="Screen Shot 2021-08-13 at 9 06 22 PM" src="https://user-images.githubusercontent.com/1461273/129430015-10964b4e-90fe-45ab-8d56-22f15d77612e.png">

Ideally, the behavior would extend to multiple DataFrames or Series. So concat would work as well.

``` python
idx_C = pd.IntervalIndex.from_tuples([(3, 5), (8, 12), (14, 20)])
df_C = pd.DataFrame(data={'C':['C1', 'C2', 'C3']}, index=idx_C)

concat_df = pd.concat([df_A, df_B, df_C], axis=1)
```
<img width="101" alt="Screen Shot 2021-08-13 at 9 14 15 PM" src="https://user-images.githubusercontent.com/1461273/129430183-e1385398-c18f-4076-a64a-4b6d8feb911c.png">


<img width="195" alt="Screen Shot 2021-08-13 at 9 14 23 PM" src="https://user-images.githubusercontent.com/1461273/129430192-96d41067-dadb-41ce-931a-e870fa24c3d7.png">


#### API breaking implications

I imagine it would be best to avoid breaking the existing behavior of merge, join, concat, etc. on IntervalArrays. I could see either creating new functions (like `pd.merge_asof`) or adding either additional parameters to the various methods or additional options to existing parameters (such as `how`).

#### Describe alternatives you've considered

I've considered just writing my own functions on that use IntervalArrays to achieve the following and looked at a number of other libraries.

* [pyranges](https://pyranges.readthedocs.io/en/master/autoapi/pyranges/index.html)
* [intervaltree](https://pypi.org/project/intervaltree/)
* [typhon](https://www.radiativetransfer.org/misc/typhon/doc/_modules/typhon/trees.html)

#### Additional context

Some other related concepts or implementations:

* [Postgres Range Functions](https://www.postgresql.org/docs/13/functions-range.html)
* [kdb+ asof joins](https://code.kx.com/q/basics/joins/#as-of-joins)
* [Wikipedia: Interval Tree](https://en.wikipedia.org/wiki/Interval_tree)
