Как использовать функцию Listagg Oracle с уникальным фильтром? [дубликат]
этот вопрос уже есть ответ здесь:
- LISTAGG в Oracle для возврата различных значений 20 ответов
у меня есть такой стол:
group_id name
-------- ----
1 David
1 John
1 Alan
1 David
2 Julie
2 Charles
и я хочу следующий результат:
group_id names
-------- -----
1 'Alan, David, John'
2 'Charles, Julie'
Я могу использовать следующий запрос:
select group_id,
listagg(name, ',') within group (order by name) as names
from demotable
group by group_id
чтобы получить это (очень похоже результат):
group_id names
-------- -----
1 'Alan, David, David, John'
2 'Charles, Julie'
любые идеи, как я могу фильтровать имена по уникальности в LISTAGG
звонок?
7 ответов
У меня нет экземпляра 11g, доступного сегодня, но не могли бы вы использовать:
SELECT group_id,
LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS names
FROM (
SELECT UNIQUE
group_id,
name
FROM demotable
)
GROUP BY group_id
супер простой ответ - решена!
select group_id,
regexp_replace(
listagg(name, ',') within group (order by name)
,'([^,]+)(,)*(,|$)', '')
from demotable
group by group_id;
это работает только при указании разделителя на', ' не ', ' ie работает только без пробелов после запятой. Если вы хотите пробелы после запятой-вот пример того, как.
select
replace(
regexp_replace(
regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')
,'([^,]+)(,)*(,|$)', '')
,',',', ')
from dual
дает Ббол, Футбол, Хоккей
мой полный ответ здесь
create table demotable(group_id number, name varchar2(100));
insert into demotable values(1,'David');
insert into demotable values(1,'John');
insert into demotable values(1,'Alan');
insert into demotable values(1,'David');
insert into demotable values(2,'Julie');
insert into demotable values(2,'Charles');
commit;
select group_id,
(select listagg(column_value, ',') within group (order by column_value) from table(coll_names)) as names
from (
select group_id, collect(distinct name) as coll_names
from demotable
group by group_id
)
GROUP_ID NAMES
1 Alan,David,John
2 Charles,Julie
select group_id,
listagg(name, ',') within group (order by name) as names
over (partition by group_id)
from demotable
group by group_id
в 11g вы можете использовать недокументированную функцию wm_concat следующим образом:
select wm_concat(distinct name) as names from demotable group by group_id
Мне нужен был этот мир кода в качестве подзапроса с некоторым фильтром данных перед агрегацией на основе внешнего запроса most, но я не смог сделать это, используя выбранный код ответа, потому что этот фильтр должен идти во внутреннем наиболее выбранном (запрос третьего уровня), а параметры фильтра были во внешнем наиболее выбранном (запрос первого уровня), что дало мне ошибку ORA-00904:"TB_OUTERMOST"."Коль": недопустимый идентификатор поскольку ANSI SQL утверждает, что ссылки на таблицы (имена корреляции) ограничены только на один уровень глубже.
Мне нужно было решение без уровней подзапроса, и этот ниже отлично работал для меня:
with
demotable as
(
select 1 group_id, 'David' name from dual union all
select 1 group_id, 'John' name from dual union all
select 1 group_id, 'Alan' name from dual union all
select 1 group_id, 'David' name from dual union all
select 2 group_id, 'Julie' name from dual union all
select 2 group_id, 'Charlie' name from dual
)
select distinct
group_id,
listagg(name, ',') within group (order by name) over (partition by group_id) names
from demotable
-- where any filter I want
group by group_id, name
order by group_id;
ниже не документируется и не рекомендуется oracle. и не может применяться в функции, показать ошибку
select wm_concat(distinct name) as names from demotable group by group_id
С уважением Зия!--2-->