#sql #oracle #oracle11g #aggregate-functions
#sql #Oracle #оракул11g #агрегатные функции
Вопрос:
listagg
работает, как и ожидалось poll_id=2
.
Как я могу выполнить то же самое для одной строки и нескольких столбцов?
with list_of_fruits as
(select 1 as poll_id ,'Apple' as first_choice, 'Pear' as second_choice, 'Peach' as third_choice, 'Plum' as fourth_choice from dual union all
select 2 as poll_id ,'Cherry' as first_choice, null as second_choice, null as third_choice, null as fourth_choice from dual union all
select 2 as poll_id ,'Grape' as first_choice, null as second_choice, null as third_choice, null as fourth_choice from dual union all
select 2 as poll_id ,'Kiwi' as first_choice, null as second_choice, null as third_choice, null as fourth_choice from dual union all
select 3 as poll_id ,'Squash' as first_choice, 'Peas' as second_choice, '' as third_choice, null as fourth_choice from dual union all
select 3 as poll_id ,null as first_choice, null as second_choice, null as third_choice, 'Barley' as fourth_choice from dual union all
select 3 as poll_id ,null as first_choice, null as second_choice, 'Oats' as third_choice, null as fourth_choice from dual
) select poll_id, listagg(first_choice,';') within group (order by poll_id) as sam
from list_of_fruits
group by poll_id
Желаемый результат
Объедините все строки и столбцы (слева направо, сверху вниз), чтобы каждый идентификатор опроса содержал только одну строку в результирующем наборе. Я хочу игнорировать нули.
1 Apple;Pear;Peach;Plum
2 Cherry;Grape;Kiwi
3 Squash;Peas;Barley;Oats
Комментарии:
1. В вашем примере, например
poll_id = 2
, все три фрукта — »first_choice
«. В каком порядке они должны отображаться в выходных данных? (Имеет ли это значение? Например, они могут отображаться в алфавитном порядке.) В противном случае, я предполагаю, что для любого данногоpoll_id
фруктаfirst_choice
сначала должны появиться фрукты, указанные в, затем те, что указаны вsecond_choice
и т. Д.?2. Да, порядок действительно имеет значение. Для каждого идентификатора выберите 1-й, 2-й, 3-й, 4-й вариант. Затем 2-й ряд, затем третий ряд и т.д..
3. @zundarz Я обновил свой ответ ниже.
4. Ваши данные не нормализованы, и хотя решение @mathguy может дать вам желаемый результат, лучшим подходом было бы изменить дизайн вашей базы данных, чтобы избежать хранения данных в формате CSV.
5. Что вы подразумеваете под «первым рядом», «вторым рядом» и т.д.? Строки в таблице не упорядочены. У вас есть еще один столбец, чтобы упорядочить строки по этому столбцу? Или вы имеете в виду «произвольный» порядок строк, но фрукты следует считывать из каждой строки, а затем переходить к другой строке?
Ответ №1:
with
list_of_fruits
( poll_id, first_choice, second_choice, third_choice, fourth_choice ) as (
select 1,'Apple' , 'Pear', 'Peach', 'Plum' from dual union all
select 2,'Cherry', '' , '' , '' from dual union all
select 2,'Grape' , '' , 'Berry', '' from dual union all
select 2,'Kiwi' , '' , '' , '' from dual union all
select 3,'Squash', 'Peas', '' , '' from dual union all
select 3,'' , '' , '' , 'Barley' from dual union all
select 3,'' , '' , 'Oats' , '' from dual
),
prep ( poll_id, first_choice, second_choice, third_choice, fourth_choice, rn ) as (
select poll_id, first_choice, second_choice, third_choice, fourth_choice,
row_number() over (partition by poll_id order by null)
from list_of_fruits
)
select poll_id, listagg(fruit, ',') within group (order by rn, choice) as sam
from prep
unpivot ( fruit for choice in (first_choice as 1, second_choice as 2,
third_choice as 3, fourth_choice as 4))
group by poll_id
order by poll_id -- ORDER BY is optional
;
POLL_ID SAM
---------- ------------------------------
1 Apple,Pear,Peach,Plum
2 Grape,Berry,Cherry,Kiwi
3 Squash,Peas,Barley,Oats
Комментарии:
1. Обратите
order by null
внимание на inrow_number()
в определенииrn
inprep
. Это означает, что строки для данногоpoll_id
будут в произвольном порядке, но они будут в некотором порядке. Если они должны быть в более определенном порядке, это можно настроить вorder by
предложении inrow_number
. Кроме того, я изменил CTE, чтобы имена столбцов указывались сразу после имени CTE. Это работает только в Oracle 11.2 и выше; для версии 11.1 вы можете переместить имена столбцов обратно в определение CTE (как они были у вас изначально) и сделать то же самое дляprep
.2. Я также добавил
'Berry'
в качествеthird_choice
в одну из строк дляpoll_id = 2
, чтобы проверить, правильно ли работает решение.