使用 SQL 迭代计算字符串 '6*5+2/8' 的输出



我知道如果我们在select语句中直接使用use,它将在中工作

从dual中选择(6*5+2/4(;

这将产生30.5的输出,但我的期望是
6*5=30+2=32/4=8它应该返回8

有这样的计算方法吗?

下面的解决方案假设所有输入都是非负整数,输入表达式中没有括号和空格,并且没有被零除。

如果输入有括号,则可以先删除这些括号。如果有空间,也可以先将其移除。如果输入可能包括分数和/或负数,那么这也可以被适应,只需要做更多的工作。

策略:首先插入括号,强制评估顺序;这显示在CCD_ 1中间结果中(在prep子查询中(。我们还需要将"/"更改为"div",以便在XQuery中使用。

然后只需使用XQuery来计算得到的算术表达式字符串。

with
test_data (str) as (
select '6*5+2/4'    from dual union all
select '332'        from dual union all
select '12+3*5/75'  from dual
)
, prep (str, new_str) as (
select str,
replace(
rpad('(', length(regexp_replace(str, 'd')), '(') ||
regexp_replace(str, '([-+*/])', ')1')
, '/', ' div ')
from   test_data
)
select str, new_str,
xmlcast(xmlquery(new_str returning content) as number) as result
from   prep;
STR        NEW_STR               RESULT
---------  -------------------  -------
6*5+2/4    (((6)*5)+2) div 4          8
332        332                      332
12+3*5/75  (((12)+3)*5) div 75        1

您可以使用递归查询:

WITH perform_calculation (value, calculation) AS (
SELECT value,
value
FROM   table_name
UNION ALL
SELECT value,
CASE REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 2)
WHEN '+' THEN REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1)
+
REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 3)
WHEN '-' THEN REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1)
-
REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 3)
WHEN '*' THEN REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1)
*
REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 3)
WHEN '/' THEN REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1)
/
REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 3)
END
|| REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 4)
FROM   perform_calculation
WHERE  REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1) IS NOT NULL
)
SEARCH DEPTH FIRST BY value SET value_order
SELECT value,
calculation
FROM   perform_calculation
WHERE  REGEXP_SUBSTR(calculation, '^(-?d+.?d*)([+*/-])(-?d+.?d*)(.*)$', 1, 1, NULL, 1) IS NULL;

对于样本数据:

CREATE TABLE table_name (value) AS
SELECT '6*5+2/4' FROM DUAL UNION ALL
SELECT '6*5+2/4' FROM DUAL UNION ALL
SELECT '32/4*3/2+24/4+3/6' FROM DUAL UNION ALL
SELECT '3/2-3*5' FROM DUAL;

输出:

VALUE计算
3/2-3*5-7.5
32/4*3/2+24/4+3/62
6*5+2/48
6*5+2/48

Division优先于加法,因此默认情况下,您的计算将为:

(6*5(+(2/4(

如果你想更改默认优先级,那么你需要使用括号:

(6*5+2(/4

最新更新