#sql #oracle #oracle11g
#sql #Oracle #oracle11g
Вопрос:
Пожалуйста, рассмотрите следующую db<>скрипку:
https://dbfiddle.uk/?rdbms=oracle_11.2amp;fiddle=8d3223f66c3f88294f84645756420836
У меня есть (упрощенная) таблица с именем sample_data
, которая выглядит следующим образом:
key values separator fields
--------------------------------------------------------
10791701 16;20; ; FIELD1;FIELD2
10791702 17|18|19| | FIELD3|FIELD4|FIELD5
То, что я хотел бы сделать здесь, это выполнить запрос, вывод которого будет следующим:
key value field
--------------------------------------------------------
10791701 16 FIELD1
10791701 20 FIELD2
10791702 17 FIELD3
10791702 18 FIELD4
10791702 19 FIELD5
То есть я хотел бы каким-то образом разделить значения в values
столбце и присвоить им соответствующее имя поля в fields
столбце.
Вот что я пробовал:
select *
from sample_data t1
left join (select t1.key, column_value from table(apex_string.split(t1.fields, t1.separator))) t2
on t1.key = t2.key;
К сожалению, это, похоже, не работает, потому что Oracle отображает: ORA-00904: "T1"."FIELDS": invalid identifier
. Мне кажется, что при использовании left join
предложения это не позволит мне использовать столбцы из t1
указанного выше псевдонима.
Как же тогда мне получить желаемый результат?
Комментарии:
1. Используйте
left join lateral
вместо этого.2. Мои извинения. Я должен был упомянуть, что здесь я работаю с Oracle 11g. IIRC,
left join lateral
доступен только из Oracle 12, правильно?
Ответ №1:
В 11g нет lateral
предложения, однако отношение из table
функции можно объединить, используя обычную старую запись через запятую.
В вашем случае проблема IMHO заключается в том, что вы объявили "fields"
идентификатор в кавычках, поэтому вам также нужно указать его в запросе.
Таким образом, окончательное решение может выглядеть так
select *
from sample_data t1,
table(apex_string.split(t1."fields", t1."separator")) t2
(Не проверено в скрипке db — функция apex там не поддерживается.)
Комментарии:
1. Проблема заключается
t1
в идентификаторах, а не в кавычках. Это не должно работать.2. @GordonLinoff Я признаю, что это противоречит здравому смыслу, хотя это работает, я использую его случайно (и проверено на моем docker с помощью эмуляции функции apex, dbfiddle имеет ограничения). Также идентификаторы в кавычках. Кажется, OP успешно применил оба моих совета в своем решении:-D
Ответ №2:
Мне удалось решить мою проблему, используя своего рода стратегию «разделяй и властвуй». Вот как это происходит:
create table SAMPLE_DATA
(
key VARCHAR2(8),
the_values VARCHAR2(10),
separator VARCHAR2(1),
the_fields VARCHAR2(20)
);
Затем я вставляю данные следующим образом:
insert into sample_data (KEY, THE_VALUES, SEPARATOR, THE_FIELDS)
values ('10791701', '16;20;', ';', 'FIELD1;FIELD2');
insert into sample_data (KEY, THE_VALUES, SEPARATOR, THE_FIELDS)
values ('10791702', '18|17|19|', '|', 'FIELD3|FIELD4|FIELD5');
insert into sample_data (KEY, THE_VALUES, SEPARATOR, THE_FIELDS)
values ('10791703', '77,99,88', ',', 'FIELD6,FIELD7,FIELD8');
Затем, наконец, используйте следующий запрос:
with t1 as
(select * from sample_data),
t2 as
(select key, row_number() over(partition by key order by null) value_index, column_value
from t1, table(apex_string.split(the_values, separator))
where column_value is not null),
t3 as
(select key, row_number() over(partition by key order by null) value_index, column_value
from t1, table(apex_string.split(the_fields, separator))
where column_value is not null)
select t1.key, t2.column_value the_value, t3.column_value the_field
from t1
left join t2
on t1.key = t2.key
left join t3
on t2.key = t3.key
and t2.value_index = t3.value_index;
Вывод
KEY THE_VALUE THE_FIELD
---------------------------------
10791701 16 FIELD1
10791701 20 FIELD2
10791702 18 FIELD3
10791702 17 FIELD4
10791702 19 FIELD5
10791703 77 FIELD6
10791703 99 FIELD7
10791703 88 FIELD8
Объяснение
По сути, таблицы t2
и t3
разделяют столбцы the_values
and the_fields
, а также извлекают индексы на основе 1 ( row_number() over(partition by key order by null)
) для каждого происходящего разделения. Все, что осталось, это объединить таблицу отношений и две другие.