Разделение таблицы на две колонки в зависимости от данных группы

Есть исходная таблица с одной колонкой V_GROUP:

V_GROUP
------------------------------
1.1. Название группы 1  
1.1.1. Данные подгруппы 1   
1.1.2. Данные подгруппы 2   
1.1.3. Данные подгруппы 3   
1.2. Название группы 2  
1.2.1. Данные подгруппы 1 (2)   
1.2.2. Данные подгруппы 2 (2)   
1.2.3. Данные подгруппы 3 (3)

Из данной таблицы нужно сделать представление с 2 колонками (V_SUBGROUP, V_GROUP), чтобы в левой колонке были подгруппы, а в правой - группы, и чтобы, конечно, правильные группы совпадали с подгруппами:

V_SUBGROUP                         V_GROUP
---------------------------------------------------------
1.1.1. Данные подгруппы 1       1.1. Название группы 1  
1.1.2. Данные подгруппы 2       1.1. Название группы 1  
1.1.3. Данные подгруппы 3       1.1. Название группы 1  
1.2.1. Данные подгруппы 1 (2)   1.2. Название группы 2
1.2.2. Данные подгруппы 2 (2)   1.2. Название группы 2
1.2.3. Данные подгруппы 3 (3)   1.2. Название группы 2

Ответы (3 шт):

Автор решения: Akina
SELECT t2.v_group v_subgroup, t1.v_group
FROM test t1
JOIN test t2 ON SUBSTRING_INDEX(t1.v_group, '.', 2) = SUBSTRING_INDEX(t2.v_group, '.', 2)
WHERE SUBSTRING_INDEX(SUBSTRING_INDEX(t1.v_group, '.', 3), '.', -1) LIKE ' %'
  AND SUBSTRING_INDEX(SUBSTRING_INDEX(t2.v_group, '.', 3), '.', -1) NOT LIKE ' %'

fiddle

→ Ссылка
Автор решения: 0xdb

Как правильно заметил в комментарии @Мike, на этапе дизайна надо было предусмотреть деление записей на группы и подгруппы с указанием их связей. Раз это не произошло, а также учитывая, что иерархия записей только двухуровневая, то проще всего с self-join:

with q as (
    select grptxt, 
        regexp_substr (grptxt, '^((\d+)\.){2}') grpid2,
        regexp_substr (grptxt, '^((\d+)\.){3}') grpid3
    from t1)
select q3.grptxt subgrptxt, q2.grptxt 
from q q2
join q q3 on (
    q3.grpid2 = q2.grpid2 
    and q2.grpid3 is null 
    and q3.grpid3 is not null)

Даст желаемый результат:

SUBGRPTXT                        GRPTXT                          
-------------------------------- --------------------------------
1.1.1. Данные подгруппы 1        1.1. Название группы 1          
1.1.2. Данные подгруппы 2        1.1. Название группы 1          
1.1.3. Данные подгруппы 3        1.1. Название группы 1          
1.2.1. Данные подгруппы 1 (2)    1.2. Название группы 2          
1.2.2. Данные подгруппы 2 (2)    1.2. Название группы 2          
1.2.3. Данные подгруппы 3 (3)    1.2. Название группы 2          

На db<>fiddle.

→ Ссылка
Автор решения: Yitzhak Khabinsky

Немного другая версия для Oracle. Повторное использование DDL из решения 0xdb. Спасибо.

Fiddle

pl/sql

WITH q as (
    SELECT substr(grptxt, 1, instr(grptxt, ' ', 1) - 1) AS hierarchy, grptxt
    FROM t1
)
SELECT p.grptxt as V_GROUP, c.grptxt as V_SUBGROUP
FROM q p LEFT OUTER JOIN q c 
   ON p.hierarchy = substr(c.hierarchy, 1, length(p.hierarchy))
WHERE length(p.hierarchy) < length(c.hierarchy);

результат

+------------------------+-------------------------------+
|        V-GROUP         |          V_SUBGROUP           |
+------------------------+-------------------------------+
| 1.1. Название группы 1 | 1.1.1. Данные подгруппы 1     |
| 1.1. Название группы 1 | 1.1.2. Данные подгруппы 2     |
| 1.1. Название группы 1 | 1.1.3. Данные подгруппы 3     |
| 1.2. Название группы 2 | 1.2.1. Данные подгруппы 1 (2) |
| 1.2. Название группы 2 | 1.2.2. Данные подгруппы 2 (2) |
| 1.2. Название группы 2 | 1.2.3. Данные подгруппы 3 (3) |
+------------------------+-------------------------------+
→ Ссылка