我有一个表 tab_1,其值如下。
ID Calculation value
1 10
2 10
3 1+2
4 5
5 3-2
6 5+1
需要帮助编写以下逻辑的查询。我有一个表,其中记录包含计算字符串或要在计算中使用的值。我需要像这样解析计算
:
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 的记录并执行计算。我的 预期输出:
ID Calculation value
3 1+2 20
5 3-2 10
6 5+1 20
谢谢——纳尼
最佳答案
"Need help writing the query for below logic."
这不是一个可以用纯 SQL 解决的问题,因为:
- 执行计算字符串需要动态SQL
- 您需要递归来查找记录并评估结果
这是一个递归函数,它可以产生您期望的答案。它有三个私有(private)过程,因此函数的主体很容易理解。在伪代码中:
- 查找记录
- 如果记录是
值
,则返回它并退出 - 否则爆炸
计算
- 对分解
计算
的每个部分递归1、3、4,直到2
抱歉需要滚动:
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;
/
像这样运行:
SQL> select dyn_calc(6) from dual;
DYN_CALC(6)
-----------
20
SQL>
或者,要完全按照您的要求获得输出:
select id, calculation, dyn_calc(id) as value
from t23
where calculation is not null;
注释
- 没有异常处理。如果数据无效,函数就会崩溃
split_calc()
过程使用translate()
来提取运算符而不是正则表达式。这是因为regexp_substr(p_calc, '[\-\+\*\%]', 1, 1)
神秘地吞掉了-
。这似乎是一个与环境相关的错误。因此,扩展这个函数来处理1+4+2
将会很尴尬。
关于sql - 需要oracle sql查询中动态计算的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48179927/