【问题标题】:Not able to execute sql query无法执行sql查询
【发布时间】:2011-05-11 11:46:08
【问题描述】:
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. 我需要选择threshold_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.现在 threshold_type 是 p_id ok 2.所以我需要从 cash_transactions 表中按 pid 分组。 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 for 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.         

编辑:假设threshold_type为null,那么我们不需要在查询中包含partition by part,那么如何获取呢?

【问题讨论】:

  • 如果您将其放入代码中并格式化行,这样您就可以看到缺少的内容,这样会更容易阅读。我的猜测是您缺少内部选择的 from 语句,但我没有 Oracle,因此无法对其进行测试...
  • How to run this query的可能重复
  • @marc_s : 是的,我没有提到细节...抱歉
  • @Paul W:我没明白你的意思
  • 请提供desc thresholdsdesc cash_transactions 的输出以及两个表的一些示例行。根据目前的信息,很难理解您要达到的目标。

标签: sql oracle subquery


【解决方案1】:

只有动态 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);

【讨论】:

  • 这个问题不清楚所需的输出,但我怀疑他不只是想要一组交易超过阈值的 ID——他可能想要每组交易超过一个门槛。但是您的回答给了我一个有趣的想法——如果将该函数转换为可以返回多行的管道,那么可以按照您的建议从一个简单的查询中调用它,并返回我认为需要的所有信息。跨度>
  • @dave costa OP 清楚地写道:"select id threshold" :),但是是的,你是对的,使用管道功能更加灵活。跨度>
  • @schurik- 让我们进行第一次 fetch .... 假设内部查询返回 10 个结果,那么内部查询有 10 个 sum_amount ,用于与阈值表的第一条记录进行比较,并且要获取对应的threshold_id
  • @schurik- 上述解决方案不会给出所需的答案
  • @gaurav 内部查询从 threshold_type 返回 Sums pro 组的最大值。对于您的 testdata,该函数将为 threshold_1 返回 500,为 threshold_2 返回 300。比您在查询中将此值与 threshold_amount 进行比较。 “threshold_2”将从查询中返回,而 100 500。需要的答案是什么?
【解决方案2】:

您的直接问题是tt 不在cash_transactions 的子查询范围内,因此您不能在该子查询中引用threshold_type。对此的语法修复是转换为一个连接,并带有一个正常的 group by。

但是,这仍然无法满足您的要求,因为它将按 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,这允许您按位置获取列值。

【讨论】:

    猜你喜欢
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多