Что вы ищете называется "pivot" (смотри также "Pivoting Operations" в базе данных Oracle Guide хранилищ данных):
SELECT *
FROM tbl
PIVOT(SUM(value) FOR Key IN (40, 41, 42))
Он был добавлен в Oracle в 11g. Обратите внимание, что вам нужно указать столбцы результатов (значения из неавторизованного столбца, которые становятся поворотными именами столбцов) в предложении pivot. Любые столбцы, не указанные в своде, неявно сгруппированы. Если в исходной таблице есть столбцы, которые вы не хотите группировать, выберите из представления или подзапроса, а не из таблицы.
Вы можете принять участие в бит wizardry и получить Oracle для создания инструкции для вас, так что вам не нужно определять, какие значения столбцов для поворота. В 11g, когда вы знаете, значение столбцов являются числовым:
SELECT
'SELECT * FROM tbl PIVOT(SUM(value) FOR Key IN ('
|| LISTAGG(Key, ',') WITHIN GROUP (ORDER BY Key)
|| ');'
FROM tbl;
Если значение столбцов не может быть числовым:
SELECT
'SELECT * FROM tbl PIVOT(SUM(value) FOR Key IN (\''
|| LISTAGG(Key, '\',\'') WITHIN GROUP (ORDER BY Key)
|| '\'));'
FROM tbl;
LISTAGG
вероятно повторяет дубликаты (? Бы кто-то проверить это), в этом случае вам нужно:
SELECT
'SELECT * FROM tbl PIVOT(SUM(value) FOR Key IN (\''
|| LISTAGG(Key, '\',\'') WITHIN GROUP (ORDER BY Key)
|| '\'));'
FROM (SELECT DISTINCT Key FROM tbl);
вы могли бы пойти дальше, определяя функцию, которая принимает имя таблицы, совокупное выражение и поворотное имя столбца, который возвращает шарнирное заявление первого р затем оценивая вышеуказанное утверждение. Затем вы можете определить процедуру, которая принимает одни и те же аргументы и создает скошенный результат. У меня нет доступа к Oracle 11g, чтобы проверить это, но я считаю, что это будет выглядеть примерно так:
CREATE PACKAGE dynamic_pivot AS
-- creates a PIVOT statement dynamically
FUNCTION pivot_stmt (tbl_name IN varchar2(30),
pivot_col IN varchar2(30),
aggr IN varchar2(40),
quote_values IN BOOLEAN DEFAULT TRUE)
RETURN varchar2(300);
PRAGMA RESTRICT_REFERENCES (pivot_stmt, WNDS, RNPS);
-- creates & executes a PIVOT
PROCEDURE pivot_table (tbl_name IN varchar2(30),
pivot_col IN varchar2(30),
aggr IN varchar2(40),
quote_values IN BOOLEAN DEFAULT TRUE);
END dynamic_pivot;
CREATE PACKAGE BODY dynamic_pivot AS
FUNCTION pivot_stmt (
tbl_name IN varchar2(30),
pivot_col IN varchar2(30),
aggr_expr IN varchar2(40),
quote_values IN BOOLEAN DEFAULT TRUE
) RETURN varchar2(300)
IS
stmt VARCHAR2(400);
quote VARCHAR2(2) DEFAULT '';
BEGIN
IF quote_values THEN
quote := '\\\'';
END IF;
-- "\||" shows that you are still in the dynamic statement string
-- The input fields aren't sanitized, so this is vulnerable to injection
EXECUTE IMMEDIATE 'SELECT \'SELECT * FROM ' || tbl_name
|| ' PIVOT(' || aggr_expr || ' FOR ' || pivot_col
|| ' IN (' || quote || '\' \|| LISTAGG(' || pivot_col
|| ', \'' || quote || ',' || quote
|| '\') WITHIN GROUP (ORDER BY ' || pivot_col || ') \|| \'' || quote
|| '));\' FROM (SELECT DISTINCT ' || pivot_col || ' FROM ' || tbl_name || ');'
INTO stmt;
RETURN stmt;
END pivot_stmt;
PROCEDURE pivot_table (tbl_name IN varchar2(30), pivot_col IN varchar2(30), aggr_expr IN varchar2(40), quote_values IN BOOLEAN DEFAULT TRUE) IS
BEGIN
EXECUTE IMMEDIATE pivot_stmt(tbl_name, pivot_col, aggr_expr, quote_values);
END pivot_table;
END dynamic_pivot;
Примечание: длина параметров в tbl_name
, pivot_col
и aggr_expr
приходит от maximum table and column name length. Также обратите внимание, что функция уязвима для SQL-инъекции.
В пред-11г вы можете применить методы MySQL pivot statement generation (который производит тип запроса, опубликованного другими пользователями, на основе явно заданного отдельного столбца для каждого значения поворота).
Работает для Oracle 11, но для более ранних версий здесь приводится путь http://www.orafaq.com/wiki/PIVOT – 2010-12-10 14:20:01