2013-03-19 3 views
6
...

шарниром (сумма (A) для B в формуле (X))Динамический поворотный в Oracle SQL

Теперь Б имеет тип данных varchar2, и Х представляет собой строку значений varchar2, разделенных запятыми.
Значения для X выбирают различные значения из столбца (скажем, CL) той же таблицы. Таким образом, работает опорный запрос.

Но проблема в том, что всякий раз, когда есть новое значение в столбце CL я должен вручную добавить, что в строке X.

Я попытался заменить X с некоторыми из различных значений CL. Но запрос не запущен.
Причина, по которой я чувствовал, была связана с тем, что для замены X нам нужны значения, разделенные запятыми.
Затем я создал функцию для возврата точного вывода в соответствие со строкой X. Но запрос все еще не запускается.
Отображаемые сообщения об ошибках похожи на «недостающие rantr parantheses», «конец канала передачи файлов» и т. Д. И т. Д.
Я попытался создать xiv вместо xpx, а запрос запускает, но дает vlaues как oraxxx и т. Д., Которые не являются значениями вообще ,

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

ответ

6

Вы не можете поместить не константную строку в предложение IN положения о свопинге.
Для этого вы можете использовать Pivot XML.

От documentation:

subquery A subquery is used only in conjunction with the XML keyword. When you specify a subquery, all values found by the subquery are used for pivoting

Он должен выглядеть следующим образом:

select xmlserialize(content t.B_XML) from t_aa 
pivot xml(
sum(A) for B in(any) 
) t; 

Вы также можете иметь подзапрос вместо ANY ключевого слова:

select xmlserialize(content t.B_XML) from t_aa 
pivot xml(
sum(A) for B in (select cl from t_bb) 
) t; 

Here is a sqlfiddle demo

+0

привет ваш метод работает на самом деле, но выход я получаю в формате XML. могу ли я получить вывод в виде таблицы со строками и столбцами? – prabhakar

+0

AFAIK, не динамически ... Но как вы намереваетесь использовать результат, который вы не знаете его структуры? –

15

Вы не можете поместить динамический оператор в инструкцию PIVOT IN без использования PIVOT XML, который выводит несколько меньше желаемого результата. Однако вы можете создать строку IN и ввести ее в свой оператор.

Во-первых, вот моя таблица образцов;

myNumber myValue myLetter 
---------- ---------- -------- 
     1   2 A   
     1   4 B   
     2   6 C   
     2   8 A   
     2   10 B   
     3   12 C   
     3   14 A  

Сначала установите строку для использования в инструкции IN. Здесь вы помещаете строку в строку «str_in_statement». Мы используем COLUMN NEW_VALUE и LISTAGG для настройки строки.

clear columns 
COLUMN temp_in_statement new_value str_in_statement 
SELECT DISTINCT 
    LISTAGG('''' || myLetter || ''' AS ' || myLetter,',') 
     WITHIN GROUP (ORDER BY myLetter) AS temp_in_statement 
    FROM (SELECT DISTINCT myLetter FROM myTable); 

Ваша строка будет выглядеть следующим образом:

'A' AS A,'B' AS B,'C' AS C 

Теперь с помощью оператора Строка в сводном запросе.

SELECT * FROM 
    (SELECT myNumber, myLetter, myValue FROM myTable) 
    PIVOT (Sum(myValue) AS val FOR myLetter IN (&str_in_statement)); 

Вот выход:

MYNUMBER  A_VAL  B_VAL  C_VAL 
---------- ---------- ---------- ---------- 
     1   2   4    
     2   8   10   6 
     3   14     12 

Есть ограничения, хотя. Вы можете конкатенировать строку до 4000 байт.

+0

при попытке этого я получаю ниже ошибки оракула: ORA-56900: привязка переменной не поддерживается внутри оси pivot | операция univot – lourdh

+0

Как реализовать это в процедуре Oracle? PLS привести пример – Ram

1

я использовал вышеупомянутый метод (Anton PL/SQL пользовательские функции поворота()), и это сделали работу ! Поскольку я не профессиональный разработчик Oracle, это простые шаги, которые я сделал:

1) Загрузите пакет zip, чтобы найти там pivotFun.sql. 2) Запустите один раз pivotFun.sql для создания новой функции 3) Используйте эту функцию в обычном SQL.

Просто будьте осторожны с именами динамических колонок. В моей среде я обнаружил, что имя столбца ограничено 30 символами и не может содержать в себе одну цитату. Итак, мой запрос в настоящее время выглядит примерно так:

SELECT 
    * 
FROM 
    table( 
     pivot(' 
       SELECT DISTINCT 
        P.proj_id, 
        REPLACE(substr(T.UDF_TYPE_LABEL, 1, 30), '''''''','','') as Attribute, 
        CASE 
         WHEN V.udf_text is null  and V.udf_date is null and  V.udf_number is NOT null THEN to_char(V.udf_number) 
         WHEN V.udf_text is null  and V.udf_date is NOT null and V.udf_number is null  THEN to_char(V.udf_date) 
         WHEN V.udf_text is NOT null and V.udf_date is null and  V.udf_number is null  THEN V.udf_text 
         ELSE NULL END 
        AS VALUE 
       FROM 
        project P 
       LEFT JOIN UDFVALUE V ON P.proj_id  = V.proj_id 
       LEFT JOIN UDFTYPE T ON V.UDF_TYPE_ID = T.UDF_TYPE_ID 
       WHERE 
        P.delete_session_id IS NULL AND 
        T.TABLE_NAME = ''PROJECT'' 
    ') 
) 

Хорошо работает с данными до 1 м.

0

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

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

Пример

Рассмотрим мы имеем таблицу, как показано ниже.

enter image description here

Если нам нужно показать значения в столбце YR в качестве имен столбцов и значений в этих колонках из QTY, то можно использовать следующий код.

declare 
    sqlqry clob; 
    cols clob; 
begin 
    select listagg('''' || YR || ''' as "' || YR || '"', ',') within group (order by YR) 
    into cols 
    from (select distinct YR from EMPLOYEE); 


    sqlqry := 
    '  
    select * from 
    (
     select * 
     from EMPLOYEE 
) 
    pivot 
    (
    MIN(QTY) for YR in (' || cols || ') 
)'; 

    execute immediate sqlqry; 
end; 
/

РЕЗУЛЬТАТ

enter image description here

При необходимости, вы можете также создать временную таблицу и сделать запрос на выборку в этом временную таблицу, чтобы увидеть результаты. Его просто, просто добавьте CREATE TABLE TABLENAME AS в вышеуказанный код.

sqlqry := 
'  
    CREATE TABLE TABLENAME AS 
    select * from 
0

ПРИМЕНЕНИЕ ДИНАМИЧЕСКОЙ QUERY

Test код ниже


-- DDL for Table TMP_TEST 
-------------------------------------------------------- 

    CREATE TABLE "TMP_TEST" 
    ( "NAME" VARCHAR2(20), 
    "APP" VARCHAR2(20) 
    ); 
/
SET DEFINE OFF; 
Insert into TMP_TEST (NAME,APP) values ('suhaib','2'); 
Insert into TMP_TEST (NAME,APP) values ('suhaib','1'); 
Insert into TMP_TEST (NAME,APP) values ('shahzad','3'); 
Insert into TMP_TEST (NAME,APP) values ('shahzad','2'); 
Insert into TMP_TEST (NAME,APP) values ('shahzad','5'); 
Insert into TMP_TEST (NAME,APP) values ('tariq','1'); 
Insert into TMP_TEST (NAME,APP) values ('tariq','2'); 
Insert into TMP_TEST (NAME,APP) values ('tariq','6'); 
Insert into TMP_TEST (NAME,APP) values ('tariq','4'); 
/
    CREATE TABLE "TMP_TESTAPP" 
    ( "APP" VARCHAR2(20) 
    ); 

SET DEFINE OFF; 
Insert into TMP_TESTAPP (APP) values ('1'); 
Insert into TMP_TESTAPP (APP) values ('2'); 
Insert into TMP_TESTAPP (APP) values ('3'); 
Insert into TMP_TESTAPP (APP) values ('4'); 
Insert into TMP_TESTAPP (APP) values ('5'); 
Insert into TMP_TESTAPP (APP) values ('6'); 
/
create or replace PROCEDURE temp_test(
    pcursor out sys_refcursor, 
    PRESULT     OUT VARCHAR2 
    ) 
AS 
V_VALUES VARCHAR2(4000); 
V_QUERY VARCHAR2(4000); 
BEGIN 
PRESULT := 'Nothing'; 

-- concating activities name using comma, replace "'" with "''" because we will use it in dynamic query so "'" can effect query. 
    SELECT DISTINCT 
     LISTAGG('''' || REPLACE(APP,'''','''''') || '''',',') 
     WITHIN GROUP (ORDER BY APP) AS temp_in_statement 
    INTO V_VALUES 
    FROM (SELECT DISTINCT APP 
      FROM TMP_TESTAPP); 

-- designing dynamic query 

    V_QUERY := 'select * 
       from ( select NAME,APP 
          from TMP_TEST ) 
       pivot (count(*) for APP in 
        (' ||V_VALUES|| ')) 
      order by NAME' ; 

    OPEN PCURSOR 
    FOR V_QUERY; 


PRESULT := 'Success'; 

Exception 
WHEN OTHERS THEN 
PRESULT := SQLcode || ' - ' || SQLERRM; 
END temp_test; 
Смежные вопросы