Преобразование подтаблиц в той же таблице в столбцы
У меня есть такая таблица:
+-------+-------+-------+-------+
| ID | City | Param | Value |
+-------+-------+-------+-------+
| id1 | city1 | a | value |
| id2 | city1 | b | value |
| id3 | city1 | c | value |
| id4 | city2 | a | value |
| id5 | city2 | b | value |
| id6 | city2 | c | value |
| ... | ... | ... | ... |
| idN | cityN | a | value |
| idN+1 | cityN | b | value |
| idN+2 | cityN | c | value |
+-------+-------+-------+-------+
Как вы можете видеть, он имеет подтаблицу для каждого города, например:
+-------+-------+
| Param | Value |
+-------+-------+
| a | value |
| b | value |
| c | value |
+-------+-------+
Поэтому я хотел бы объединить все подтаблицы и получить таблицу, подобную этой:
+-------+-------+-------+-----+-------+
| Param | city1 | city2 | ... | cityN |
+-------+-------+-------+-----+-------+
| a | value | value | ... | value |
| b | value | value | ... | value |
| c | value | value | ... | value |
+-------+-------+-------+-----+-------+
Любые идеи, как я могу получить это?
Заранее спасибо!
Примечание 1: Количество городов является переменным.
Примечание 2: Решением может быть функция PL/SQL.
2 ответа
Чтобы получить желаемый результат, вам нужно повернуть данные. В то время как вы сказали, что plsql может быть вариантом, вы не указали, какую версию Oracle вы используете. Начиная с Oracle 11g, PIVOT
функция была сделана доступной.
Если вы не используете Oracle 119, то вы можете использовать агрегатную функцию с CASE
выражение:
select param,
max(case when city = 'city1' then value end) City1,
max(case when city = 'city2' then value end) City2
from yourtable
group by param
Смотрите SQL Fiddle с демонстрацией.
Поскольку вы заявляете, что у вас будет неизвестное количество city
значения, то вам нужно будет создать динамическую SQL-версию этого запроса. Вы можете создать процедуру, подобную этой:
CREATE OR REPLACE procedure dynamic_pivot(p_cursor in out sys_refcursor)
as
sql_query varchar2(1000) := 'select param ';
begin
for x in (select distinct city from yourtable order by 1)
loop
sql_query := sql_query ||
' , max(case when city = '''||x.city||''' then value else null end) as '||x.city;
dbms_output.put_line(sql_query);
end loop;
sql_query := sql_query || ' from yourtable group by param order by param';
dbms_output.put_line(sql_query);
open p_cursor for sql_query;
end;
/
Затем, чтобы получить свой результат, вы можете использовать следующее (примечание: я использовал это в TOAD):
variable x refcursor
exec dynamic_pivot(:x)
print x
И результат вашего запроса будет:
| PARAM | CITY1 | CITY2 |
-------------------------
| a | value | value |
| b | value | value |
| c | value | value |
Вы можете использовать новый pivot
в 11G или model
оговорка, если у вас есть 10G. проверьте документы.