Не удалось выполнить SQL-запрос - PullRequest
2 голосов
/ 11 мая 2011
select tt.threshold_id
from   (select sum(amount) over (partition by tt.threshold_type 
                                     order by tt.threshold_type ) amt
        from   cash_transactions) cash,
       thresholds tt
where  tt.threshold_amount < cash.amt  

rdms - это oracle, ошибка:

" ORA-00904: "TT"."THRESHOLD_TYPE": invalid identifier"

, что я хочу сделать с этим запросом:

  1. таблица порогов содержит тип порога столбца, которыйсодержит имя столбца таблицы операций с наличными
  2. И для каждой записи из таблицы порогов необходимо сравнить группу сумм (сумм) по типу порога из таблицы операций с наличными.
  3. и суммуизвлечено сравнивается с threshold_amount таблицы порогов
  4. , и мне нужно выбрать порог_id

Таблица порогов:

Threshold_id        Threshold_type          Threshold_amount
============================================================
threshold_1         p_id                    450
threshold_2         p_id,to_acc_main_num    100 

Таблица транзакций наличными:

Tran_inst_id    p_id    amount    to_acc_main_num
=================================================
1               E1      100       123
2               E2      200       5765  
3               E1      200       687
4               E2      300       890
5               E1      100       462

ЖЕЛАЕМЫЙ ВЫХОД:

Давайте возьмем первую выборку: первая запись из таблицы порогов

Threshold_id        Threshold_type          Threshold_amount
============================================================
threshold_1         p_id                    100000

1. теперь тип_порога равен p_id ок 2.Soмне нужно сгруппировать по pid из таблицы cash_transactions.3. так что желаемый результат из этого (но я должен взять сумму только на основе p_id), а не tran_inst_id в этом случае

Tran_inst_id  p_id    sum(amount)
======================================
1             E1        400
2             E2        500
3             E1        400
4             E2        500
5             E1        400

1. Теперь количество каждой записи выше сравнивается с величиной threshold_1запись.2.so 450 threshold_amount для threshold_1 сравнивается со всеми вышеупомянутыми записями 3.so требуемый результат будет

theshold_id   Tran_inst_id
==================================
thresold_1      2
threshold_1     4 
- the above result is for first record of threshold table ,now the same continues for the second record.         

EDIT: Предположим, если threshold_type имеет значение null, тогда нам не нужно включать разделение по частям взапрос, то как его можно получить?

Ответы [ 2 ]

2 голосов
/ 11 мая 2011

Это возможно только с динамическим sql, поскольку количество столбцов в предложении group by является переменным.Например, с функцией:

    create or replace
    function sum_cash_transactions ( p_threshold_type varchar2) return number
    is
      v_result NUMBER;
    begin
      execute immediate ' select max( sum_amount) 
                          from( select sum(amount) as sum_amount
                                from   cash_transactions
                                group by ' || p_threshold_type || ' )'
     into v_result;
     return v_result;
     end;
/

, а затем

select threshold_id
 from thresholds
 where threshold_amount < sum_cash_transactions(threshold_type);

РЕДАКТИРОВАТЬ в соответствии с новыми требованиями:

CREATE OR REPLACE package pkg AS
  TYPE res_rec_type IS RECORD (
    threshold_id  VARCHAR2(200)
  , Tran_inst_id  NUMBER(10,0)
  , sum_amount    NUMBER(22)
  );
  TYPE res_tab_type IS TABLE of res_rec_type;
  FUNCTION f1 RETURN  res_tab_type PIPELINED;
END;
/

CREATE OR REPLACE PACKAGE BODY pkg AS

  FUNCTION f1 RETURN  res_tab_type PIPELINED
  IS
    CUR    SYS_REFCURSOR;
    v_rec  res_rec_type;
  BEGIN
    FOR treshold in ( SELECT Threshold_id,  Threshold_type,   Threshold_amount FROM thresholds)
    LOOP
      OPEN CUR FOR 'SELECT ' || threshold.Threshold_id || ', tTran_inst_id,  s FROM (SELECT  tTran_inst_id, SUM(AMOUNT) OVER (PARTITION BY ' || p_Threshold_type || ') as s from cash_transactions ) WHERE s > ' || treshold.Threshold_amount ;
      LOOP
        FETCH cur INTO v_rec;
        EXIT WHEN cur%NOTFOUND;
        pipe row(v_rec);
      END LOOP;
    END LOOP;
    CLOSE cur;
    RETURN;
  END;
END;
/

SELECT * form table(pkg.f1);
1 голос
/ 11 мая 2011

Ваша непосредственная проблема заключается в том, что tt не входит в область действия подзапроса на cash_transactions, поэтому вы не можете ссылаться на threshold_type в этом подзапросе. Синтаксическим исправлением для этого будет преобразование в объединение с нормальной группой по.

Тем не менее, это все равно не будет выполнять то, что вы хотите, потому что оно будет группировать по значениям, содержащимся в threshold_type - оно не будет интерпретироваться как список столбцов, по которым на самом деле группируются. Анализатор запросов должен знать столбцы, на которые ссылаются во время разбора, и вы пытаетесь определить их во время выполнения.

Стандартный способ справиться с этим - это динамический SQL, где вы создаете запрос как строку в процедурном коде, а затем явно анализируете и выполняете его. Простая реализация в PL / SQL будет выглядеть так:

FOR tt in (SELECT * from thresholds) LOOP
  OPEN a_refcursor FOR 'SELECT SUM(amount) FROM cash_transactions GROUP BY '
                       ||tt.threshold_type||
                       ' HAVING SUM(amount) > '||TO_CHAR(tt.threshold_amount);
  LOOP
    FETCH a_refcursor INTO local_var;
    EXIT WHEN a_refcursor%NOTFOUND;
    -- do whatever it is you want to do with the information here
  END LOOP;
END LOOP;

Однако я предполагаю, что вы хотели бы знать значения динамических столбцов, для которых превышен порог. Это можно легко добавить к запросу:

  OPEN a_refcursor FOR 'SELECT '|| tt.threshold_type ||
                       ',SUM(amount) FROM cash_transactions GROUP BY '
                       ||tt.threshold_type||
                       ' HAVING SUM(amount) > '||TO_CHAR(tt.threshold_amount);

Но проблема в том, что число столбцов, возвращаемых динамическим запросом, теперь является переменным, поэтому оператор FETCH не будет работать. В этом случае вам придется использовать вызовы DBMS_SQL для обработки динамического SQL, который позволяет извлекать значения столбцов по позициям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...