首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在oracle sql查询中需要动态计算的帮助

在oracle sql查询中需要动态计算的帮助
EN

Stack Overflow用户
提问于 2018-01-10 03:36:16
回答 2查看 192关注 0票数 2

我有一个具有以下值的表tab_1。

代码语言:javascript
复制
ID Calculation value
1                10
2                10
3    1+2         
4                 5
5    3-2          
6    5+1

需要帮助编写以下逻辑的查询。我有一个表,其中的记录包含计算字符串或用于计算的值。我需要像这样解析calculation

代码语言:javascript
复制
ID 3 is the sum of ID 1 and 2.
ID 5 is the minus of ID 3 and 2.
ID 6 is the sum of ID 5 and 1.

然后,我需要为引用的ID选择记录并执行计算。我的预期产出:

代码语言:javascript
复制
ID Calculation value
3    1+2         20
5    3-2         10
6    5+1         20

-谢谢--纳尼

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-12 07:11:04

“需要帮助编写下面的逻辑查询。”

这不是可以在纯SQL中解决的问题,因为:

  • 执行计算字符串需要动态SQL。
  • 您需要递归来查找记录并评估结果。

下面是一个递归函数,它生成您期望的答案。它有三个私人过程,使主体的功能很容易理解。在伪码中:

  1. 查找记录
  2. 如果记录为value,则返回它并退出
  3. 否则会爆炸calculation
  4. 将爆炸的calculation的每一部分恢复1,3,4,直到2

为需要滚动表示歉意:

代码语言:javascript
复制
create or replace function dyn_calc
     (p_id in number)
      return number
is 
    result number;
    n1 number;
    n2 number;
    l_rec t23%rowtype;
    l_val number;

    type split_calc_r is record (
        val1 number
        , operator varchar2(1)
        , val2 number
    );
    l_calc_rec split_calc_r;

    function get_rec
        (p_id in number)
        return t23%rowtype
    is 
        rv t23%rowtype;
    begin
        select *
        into rv   
        from t23
        where id = p_id;
        return rv;
    end get_rec;    

    procedure split_calc
       (p_calc in varchar2
        , p_n1 out number
        , p_n2 out number
        , p_operator out varchar2)
    is
    begin
         p_n1 := regexp_substr(p_calc, '[0-9]+', 1, 1);
         p_n2 := regexp_substr(p_calc, '[0-9]+', 1, 2);
         p_operator := translate(p_calc, '-+*%01923456789','-+*%'); --regexp_substr(p_calc, '[\-\+\*\%]', 1, 1);
    end split_calc;

    function exec_calc 
        (p_n1 in number
          , p_n2 in number
          , p_operator in varchar2)
        return number
    is 
        rv number;
    begin
        execute immediate
            'select :n1 ' ||  p_operator ||  ' :n2 from dual'
            into rv
            using p_n1, p_n2; 
        return rv;
    end exec_calc;    

begin
    l_rec := get_rec(p_id);

    if l_rec.value is not null then
        result := l_rec.value;
    else        
         split_calc(l_rec.calculation
                     , l_calc_rec.val1
                     , l_calc_rec.val2
                     , l_calc_rec.operator);
         n1 := dyn_calc (l_calc_rec.val1);
         n2 := dyn_calc (l_calc_rec.val2);
         result := exec_calc(n1, n2, l_calc_rec.operator);
    end if;

    return result;
end;
/

像这样跑:

代码语言:javascript
复制
SQL>  select dyn_calc(6) from dual;

DYN_CALC(6)
-----------
20

SQL>

或者,要完全按照您的要求获得输出:

代码语言:javascript
复制
select id, calculation, dyn_calc(id) as value
from t23
where calculation is not null;

Notes

  • 没有例外处理。如果数据无效,该函数就会爆炸。
  • split_calc() proc使用translate()来提取操作符,而不是regex。这是因为regexp_substr(p_calc, '[\-\+\*\%]', 1, 1)神秘地吞噬了-。这似乎是一个与环境相关的bug。因此,将此函数扩展到处理1+4+2将很尴尬。

这是一个LiveSQL演示

票数 3
EN

Stack Overflow用户

发布于 2018-01-10 04:00:24

In SQL:

代码语言:javascript
复制
select 'ID ' +ID+ ' is the ' + case when calculation like '%-%' then ' minus '
when calculation like '%+%' then ' sum ' END +' of  
ID'+replace(replace(calculation,'+',' and '),'-',' and ')
from tab_1
where calculation is not null

甲骨文的

代码语言:javascript
复制
select 'ID ' ||ID|| ' is the ' || case when calculation like '%-%' then ' minus '
when calculation like '%+%' then ' sum ' END|| ' of 
ID'||replace(replace(calculation,'+',' and '),'-',' and ')
from tab_1
where calculation is not null
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48179927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档