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"
我想用这个查询做的是:
阈值表:
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.现在threshold_type是p_id ok 2.所以我需要通过cash_transactions表中的pid进行分组。 因此,期望的结果是(但我必须仅根据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将threshold_1的threshold_amount与上述所有记录进行比较 3.所需的输出将是
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.
编辑:假设如果threshold_type为null,那么我们不需要在查询中按部分包含分区,那么如何获取它?
答案 0 :(得分:2)
只能使用动态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 :(得分:1)
您的直接问题是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,这允许您按位置获取列值。