Разделение таблицы на две колонки в зависимости от данных группы
Есть исходная таблица с одной колонкой 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 ' %'
Автор решения: 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. Спасибо.
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) |
+------------------------+-------------------------------+