Oracle группировка / изменение строк в столбцы - PullRequest
1 голос
/ 09 декабря 2011

У меня есть следующая таблица с именем foo:

ID | KEY  | VAL
----------------
 1 | 47   | 97
 2 | 47   | 98
 3 | 47   | 99
 4 | 48   | 100
 5 | 48   | 101
 6 | 49   | 102

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

UNIQUE_ID        | KEY  | ID1 | VAL1 | ID2 | VAL2 | ID3 | VAL3
--------------------------------------------------------------
47_1:97_2:98_3:99|  47  | 1   |  97  | 2   |  98  |  3  | 99
48_4:100_5:101   |  48  | 4   |  100 | 5   |  101 |     |  
49_6:102         |  49  | 6   |  102 |     |      |     | 

Итак, в основном все строки стот же ключ получить свернутым в 1 ряд.Может быть где-то от 1-3 строк на значение KEY

Есть ли способ сделать это в SQL-запросе (без написания хранимой процедуры или сценариев)?

Если нет, я мог бытакже работайте с менее желательным выбором

UNIQUE_ID        | KEY  | IDS   | VALS 
--------------------------------------------------------------
47_1:97_2:98_3:99|  47  | 1,2,3 | 97,98,99
48_4:100_5:101   |  48  | 4,5   | 100, 101 
49_6:102         |  49  | 6     | 102 

Спасибо!

ОБНОВЛЕНИЕ:

К сожалению, моя реальная проблема кажется гораздо более сложной, чем этот пример, иУ меня возникают проблемы при работе любого из примеров :( Мой запрос содержит более 120 строк, поэтому отправлять его не очень просто. Это выглядит примерно так:

with v_table as (select ...), 
  v_table2 as (select foo from v_table where...), 
  v_table3 as (select foo from v_table where ...),
  ...
  v_table23 as (select foo from v_table where ...)
  select distinct (...) as "UniqueID", myKey, myVal, otherCol1, ..., otherCol18 
  from tbl1 inner join tbl2 on...
  ... 
  inner join tbl15 on ...

Если я попробую любой из методов нижеКажется, что я не могу правильно выполнить группирование по причине того, что все остальные данные возвращаются. Пример:

with v_table as (select ...), 
  v_table2 as (select foo from v_table where...), 
  v_table3 as (select foo from v_table where ...),
  ...
  v_table23 as (select foo from v_table where ...)
  select "Unique ID",
   myKey, max(decode(id_col,1,id_col)) as id_1, max(decode(id_col,1,myVal)) as val_1,
   max(decode(id_col,2,id_col)) as id_2,max(decode(id_col,2,myVal)) as val_2,
   max(decode(id_col,3,id_col)) as id_3,max(decode(id_col,3,myVal)) as val_3
  from (
    select distinct (...) as "UniqueID", myKey, row_number() over (partition by myKey order by id) as id_col, id, myVal, otherCol1, ..., otherCol18 
    from tbl1 inner join tbl2 on...
    ... 
    inner join tbl15 on ...
  ) group by myKey;

Дает мне ошибку: ORA-00979: не выражение GROUP BY

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

Любая помощь будет принята!

Ответы [ 3 ]

4 голосов
/ 09 декабря 2011

Взгляните на эту статью о функции Listagg , она поможет вам получить результаты через запятую, она работает только в версии 11g.

2 голосов
/ 09 декабря 2011

Как подсказывает @OD, вы можете сгенерировать менее желательную версию с помощью LISTAGG , например (с помощью CTE для генерации ваших данных выборки):

with foo as (
select 1 as id, 47 as key, 97 as val from dual
union select 2,47,98 from dual
union select 3,47,99 from dual
union select 4,48,100 from dual
union select 5,48,101 from dual
union select 6,49,102 from dual
)
select key ||'_'|| listagg(id ||':' ||val, '_')
        within group (order by id) as unique_id,
    key,
    listagg(id, ',') within group (order by id) as ids,
    listagg(val, ',') within group (order by id) as vals
from foo
group by key
order by key;

UNIQUE_ID          KEY IDS                  VALS
----------------- ---- -------------------- --------------------
47_1:97_2:98_3:99   47 1,2,3                97,98,99
48_4:100_5:101      48 4,5                  100,101
49_6:102            49 6                    102

С немного большимманипуляцией вы можете получить желаемые результаты:

with foo as (
select 1 as id, 47 as key, 97 as val from dual
union select 2,47,98 from dual
union select 3,47,99 from dual
union select 4,48,100 from dual
union select 5,48,101 from dual
union select 6,49,102 from dual
)
select unique_id, key,
    max(id1) as id1, max(val1) as val1,
    max(id2) as id2, max(val2) as val2,
    max(id3) as id3, max(val3) as val3
from (
    select unique_id,key,
        case when r = 1 then id end as id1, case when r = 1 then val end as val1,
        case when r = 2 then id end as id2, case when r = 2 then val end as val2,
        case when r = 3 then id end as id3, case when r = 3 then val end as val3
    from (
        select key ||'_'|| listagg(id ||':' ||val, '_')
                within group (order by id) over (partition by key) as unique_id,
            key, id, val,
            row_number() over (partition by key order by id) as r
        from foo
    )
)
group by unique_id, key
order by key;

UNIQUE_ID          KEY  ID1 VAL1  ID2 VAL2  ID3 VAL3
----------------- ---- ---- ---- ---- ---- ---- ----
47_1:97_2:98_3:99   47    1   97    2   98    3   99
48_4:100_5:101      48    4  100    5  101
49_6:102            49    6  102

Не могу не почувствовать, что должен быть более простой способ ...

2 голосов
/ 09 декабря 2011

Вы можете попробовать это

select key,
    max(decode(id_col,1,id_col)) as id_1,max(decode(id_col,1,val)) as val_1,
    max(decode(id_col,2,id_col)) as id_2,max(decode(id_col,2,val)) as val_2,
    max(decode(id_col,3,id_col)) as id_3,max(decode(id_col,3,val)) as val_3
from (
        select key, row_number() over (partition by key order by id) as id_col,id,val
        from your_table
    )
group by key
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...