Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Oracle Tutorial.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
401.64 Кб
Скачать

"Расклейка" и "склейка" строк.

В этом разделе рассмотрим часто возникающие задачи по склейке и расклейке строк. Здесь применяются регулярные выражения и иерархические запросы. Не обязательно глубоко вникать в эти примеры, главное научиться писать такие же запросы на других структурах данных.

“Расклейка” одной строки.

Часто возникают задачи, когда в запросе из строки вида 'A2,8F8,J5,I77' необходимо сделать 4 строки:

A2

8F8

J5

I77

Применяя иерархический запрос и регулярные выражения, напишем запрос, который "расклеивает" строку, делая из нее несколько строк:

select regexp_substr(s, '[^,]+', 1, level) piece

from (select 'A2,8F8,J5,I77' s from dual)

connect by regexp_substr(s, '[^,]+', 1, level) is not null;

“Расклейка” нескольких строк с группировкой.

Теперь приведу волшебный запрос, который делает “расклейку” не по одной строке, а по всей таблице с группировкой:

with sample_table as

(select 'id1' col1, 'aaa,bb,cccc' col2

from dual

union all

select 'id2', 'ddd'

from dual

union all

select 'id3', 'fff,ggg' from dual)

select col1, regexp_substr(col2, '[^,]+', 1, column_value) col2

from sample_table,

table(cast(multiset

(select level

from dual

connect by regexp_instr(col2, '[^,]+', 1, level) > 0) as

sys.odcinumberlist))

order by col1, column_value;

“Склейка” в одну строку.

Также часто возникают задачи когда, наоборот, в запросе из 4 различных строк вида

A2

8F8

J5

I77

необходимо сделать склеенную строку ' 8F8,A2,I77,J5' (упорядочив по значениям, за это отвечает “over(order by id)”):

Применяя функцию sys_connect_by_path, пошагово склеиваем строку:

select ids

from (select ltrim(sys_connect_by_path(id, ','), ',') as ids, level

from (select id, lag(id) over(order by id) as prev_id

from (select 'A2' id

from dual

union all

select '8F8' id

from dual

union all

select 'J5' id

from dual

union all

select 'I77' id from dual))

start with prev_id is null

connect by prev_id = prior id

order by level desc)

where rownum = 1;

“Склейка” нескольких строк с группировкой.

Еще одним способом склеить строку является использование агрегирующей функции WM_CONCAT (она склеивает только через запятую):

select pk, wm_concat(id)

from (select 1 pk, 'A2' id

from dual

union all

select 1 pk, '8F8' id

from dual

union all

select 1 pk, 'J5' id

from dual

union all

select 1 pk, 'I77' id

from dual

union all

select 2 pk, 'GGG' id

from dual

union all

select 2 pk, 'HH69' id from dual)

group by pk;

Далее приведу запрос, который склеивает данные с группировкой и сортировкой склеиваемых данных в указанном порядке. Рассмотрим таблицу людей и их хобби с датой начала увлечения. Склеим набор хобби каждого человека в порядке начала увлечения:

with a as

(select /*+ materialize*/

'Прохоров' name,

'играть в политику' hobby,

to_date('20.05.2011', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Абрамович' name,

'кататься на яхте' hobby,

to_date('17.11.2005', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Прохоров' name,

'отдыхать в Куршавеле' hobby,

to_date('31.01.2007', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Вексельберг' name,

'покупать яйца Фаберже' hobby,

to_date('20.02.2004', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Абрамович' name,

'покупать футболистов' hobby,

to_date('11.06.2003', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Прохоров' name,

'изобретать Ё-мобили' hobby,

to_date('29.09.2009', 'dd.mm.yyyy') hobby_start_date

from dual)

select name, max(hobby_list) keep(dense_rank last order by lvl)

from (select name,

ltrim(sys_connect_by_path(hobby, ','), ',') as hobby_list,

level lvl

from (select name,

hobby,

lag(hobby) over(partition by name order by hobby_start_date) as prev_hobby

from a)

start with prev_hobby is null

connect by name = prior name

and prev_hobby = prior hobby)

group by name

order by name;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]