首页 > 解决方案 > T-SQL 将算术公式转换为其组件

问题描述

问题陈述:我有一个公式列,其中包含算术运算。我想从公式中提取变量名称,并用逗号分隔变量并创建一个新列“公式组件”

The variable names follow the particular pattern - '%[^A-Za-z,_0-9 ]%' 

但是,如果“方括号”要出现在公式中,我也想保留它们。

为了显示,

输入数据:

ID    |    Formula
------|-------------------------------------------
1     |    ([x1] + [x2]) / 100
2     |    ([y1] - [x2]) * 100 
3     |    z1 - z3 
4     |    [z4] % z3 
5     |    ((x1 * 2) + ((y1 + 2)/[x1])*[z3])/100   

期望的输出

ID    |    Formula                                |   FormulaComponents
------|------------------------------------------ |-----------------
1     |   ([x1] + [x2]) / 100                     |  [x1],[x2]
2     |   ([y1] - [x2]) * 100                     |  [y1],[x2]
3     |   z1 - z3                                 |  [z1],[z3]
4     |   [z4] % z3                               |  [z4],[z3]
5     |   ((x1 * 2) + ((y1 + 2)/[x1])*[z3])/100   |  [x1],[y1],[z3]

正如你在上面看到的,

PS:“FormulaComponents”列中出现的变量顺序无关紧要。例如,在第 5 行,顺序可以是 [y1]、[z3]、[x1] OR [z3]、[x1]、[y1] 等等

总结一下:我想在 T-SQL 中编写一个 SELECT 语句来创建这个新列。

标签: sqlsql-serverreplace

解决方案


您可以使用拆分字符串string_split(),然后仔细重新聚合结果:

select *
from t cross apply
     (select string_agg('[' + value + ']', ',') as components
      from (select distinct replace(replace(value, '[', ''), ']', '') as value
            from string_split(replace(replace(replace(replace(t.formula, '(', ' '), ')', ' '), '*', ' '), '/', ' '), ' ') s
            where value like '[[a-z]%'
           ) s
     ) s;

是一个 db<>fiddle。

这比必要的更难,因为您的公式没有规范格式。如果所有变量都用方括号括起来会更简单。或者,如果所有运算符都被空格包围。

编辑:

SQL Server 2016 有string_split()但没有string_agg(). 该风扇将替换为 XML“东西”:

您可以使用拆分字符串string_split(),然后仔细重新聚合结果:

select *
from t cross apply
     (select stuff( (select distinct ',[' + value + ']'
                     from (select distinct replace(replace(value, '[', ''), ']', '') as value
                           from string_split(replace(replace(replace(replace(t.formula, '(', ' '), ')', ' '), '*', ' '), '/', ' '), ' ') s
                           where value like '[[a-z]%'
                          ) t
                     order by 1
                     for xml path ('')
                    ), 1, 1, '') as components
     ) s;

推荐阅读