2016-07-01 2 views
0

для Oracle 12c ... У меня есть таблица позиций, проданных компании. Эта таблица имеет иерархию уровня 3 уровня, которая была продана этой компании. Одним из столбцов является название компании. Мне нужна помощь в написании SQL для создания разделенного запятыми, уникального списка имен ВСЕХ людей, во всех трех столбцах, во всех рядах, проданных этой компании. Для примера ...Oracle Использование ListAgg, различные значения, для нескольких столбцов

CompanyName Rep  Manager  GVP 
----------- ------- -------- -------- 
Sears  Bob  Tim  Frank 
Sears  Jack  Tim  Frank 
Ace   Scott Chris  Bill 

Когда я смотрю на Sears, SQL должен возвращать «Боб, Джек, Тим, Фрэнк». ORDER имен не имеет значения, только что они уникальны и что они включают имена из всех трех полей. Я бы предположил, что это тип ListAgg запроса, но может быть неправильно ...

ответ

3

Используйте оператор UNPIVOT (он будет делать только одно сканирование таблицы, тогда как с помощью UNION будет, как правило, один просмотр таблицы для каждого SELECT в unioned заявлении):

Настройка Oracle:

CREATE TABLE table_name (CompanyName, Rep, Manager, GVP) AS 
SELECT 'Sears', 'Bob', 'Tim', 'Frank' FROM DUAL UNION ALL 
SELECT 'Sears', 'Jack', 'Tim', 'Frank' FROM DUAL UNION ALL 
SELECT 'Ace', 'Scott', 'Chris', 'Bill' FROM DUAL; 

Запрос:

SELECT CompanyName, 
     LISTAGG(Name, ',') WITHIN GROUP (ORDER BY Name) AS Names 
FROM (
    SELECT DISTINCT 
     CompanyName, 
     Name 
    FROM table_name 
    UNPIVOT(name FOR typ IN (Rep, Manager, GVP)) 
) 
GROUP BY CompanyName; 

Выход:

COMPANYNAME NAMES 
----------- ------------------ 
Ace   Bill,Chris,Scott 
Sears  Bob,Frank,Jack,Tim 
+0

Я выбрал этот подход в качестве ответа из-за того, что ему нужно было только один раз прочитать данные. В качестве бонуса, я должен признаться, я никогда не видел CTAS (create table as select), используемого таким образом. Мне это нравится. – user1009073

2

Вы должны UNPIVOT данные (для удаления дубликатов), а затем перегруппировываться его:

select companyname, listagg(person, ',') within group (order by person) as persons 
from ((select companyname, repfrom as person t) union 
     (select companyname, manager from t) union 
     (select companyname, gvp from t) 
    ) t 
group by companyname; 
0

Этот SQL должен делать трюк:

select listagg(p, ', ') within group (order by p) from (
    select rep p 
    from your_table 
    union 
    select manager p 
    from your_table 
    union 
    select gvp p 
    from your_table); 
+0

Это не разбивает имена от 'CompanyName'. – MT0

+0

Да, это правильно, но это показывает общую идею сначала использовать 'UNION' для удаления дубликатов, а затем' LISTAGG' для агрегации. –

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