2013-05-02 2 views
0

У меня есть таблица, где несколько номеров учетных записей связаны с разными идентификаторами (DR_NAME). У каждой учетной записи может быть всего 0 учетных записей и до 16. Я считаю, что UNPIVOT будет работать, но я нахожусь в Oracle 10g, что не поддерживает это.Как вернуть несколько значений столбцов в виде новых строк в Oracle 10g?

DR_NAME ACCT1 ACCT2 ACCT3 ACC4 
====================================== 
SMITH  1234 
JONES  5678 2541 2547 
MARK  NULL  
WARD  8754 6547 

Я хочу, чтобы отобразить новую строку для каждого имени только 1 номер счета в строке

DR_NAME ACCT 
============== 
SMITH  1234 
JONES  5678 
JONES  2541 
JONES  2547 
MARK  NULL 
WARD  8754 
WARD  6547 
+0

Сколько строк данных вам нужно сделать, это в одном запросе, и вам нужно просто выбрать эти данные или вставить их в таблицу? –

+0

@DavidAldridge Около 1500 строк исходных данных, которые я оцениваю, могут составлять около 6000 строк, когда каждый DR_NAME соединен только с 1 ACCT. Его нужно будет вставить в таблицу. – user2249376

ответ

1

Oracle 10g не имеет UNPIVOT функцию, но вы можете использовать UNION ALL запрос UNPIVOT столбцы в строках:

select t1.DR_NAME, d.Acct 
from yourtable t1 
left join 
(
    select DR_NAME, ACCT1 as Acct 
    from yourtable 
    where acct1 is not null 
    union all 
    select DR_NAME, ACCT2 as Acct 
    from yourtable 
    where acct2 is not null 
    union all 
    select DR_NAME, ACCT3 as Acct 
    from yourtable 
    where acct3 is not null 
    union all 
    select DR_NAME, ACCT4 as Acct 
    from yourtable 
    where acct4 is not null 
) d 
    on t1.DR_NAME = d.DR_NAME; 

См. SQL Fiddle with Demo.

Этот запрос использует UNION ALL для преобразования столбцов в строки. Я включил предложение where, чтобы удалить любые значения null, иначе вы получите несколько строк для каждой учетной записи, где значение acct равно null. Исключая значения null, вы потеряете dr_name = Mark, которые вы показали, что хотите в конечном результате. Чтобы включить строки, которые имеют только значения null, я снова добавил соединение к таблице.

+0

. Вы хотите добавить предикаты, чтобы избежать возврата нулей. –

+0

@DavidAldridge. Вы правы, я немного изменил его, потому что они действительно хотят вернуть все значения «DR_NAME». Если я исключу «null», тогда они не получат «Mark» – Taryn

+0

@ user2249376 Я не уверен, что вы имеете в виду? Я показываю на основе вашего примера несколько строк для каждого имени dr_name - http://www.sqlfiddle.com/#!4/b8801/10 - Jones имеет 3 строки, Mark = 1, Smith = 1 и Ward = 2 – Taryn

1

Наиболее эффективный способом я знаю, что это сделать перекрестное соединение с некоторой логикой:

select * 
from (select t.dr_name, 
      (case when n.n = 1 then acct1 
        when n.n = 2 then acct2 
        when n.n = 3 then acct3 
        when n.n = 4 then acct4 
       end) as acct 
     from t cross join 
      (select 1 as n from dual union all 
      select 2 from dual union all 
      select 3 from dual union all 
      select 4 from dual 
      ) n 
    ) s 
where acct is not null 

union all подхода типичных результатов при сканировании таблицы один раз для каждого подзапроса. Такой подход обычно сканирует таблицу один раз.

1

Если вы заинтересованы только в вставке этих записей, то посмотрите на многопользовательскую вставку - одно сканирование данных и несколько сгенерированных строк, поэтому он очень эффективен.

примеры кода здесь: http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9014.htm#SQLRF01604

Обратите внимание, что вы можете ссылаться на ту же таблицу несколько раз, используя синтаксис вдоль линий ...

insert all 
    when acct1 is not null then into target_table (..) values (dr_name,acct1) 
    when acct2 is not null then into target_table (..) values (dr_name,acct2) 
    when acct3 is not null then into target_table (..) values (dr_name,acct3) 
    when acct4 is not null then into target_table (..) values (dr_name,acct4) 
select 
    dr_name, 
    acct1, 
    acct2, 
    acct3, 
    acct4 
from my_table. 
+0

Спасибо. Я попробую это. У меня есть решение, которое в настоящее время работает, но это может быть более эффективным. – user2249376

Смежные вопросы