Oracle SQL — повторное использование столбца из первой таблицы в предложении LEFT JOIN

#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) ) для каждого происходящего разделения. Все, что осталось, это объединить таблицу отношений и две другие.