You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server字符串列解析:拆分正负值与乘数至不同列

解析SQL Server中的表达式字符串,分离正负项及乘数

我明白你现在需要解析SQL Server里这些包含SUM表达式的字符串,把每个项按正负分开,还要提取对应的乘数。之前用CHARINDEX和普通拆分方法没搞定,那我们可以用递归CTE来拆分每个表达式的各个项,再结合字符串函数处理符号、乘数和字段名,下面是具体的可运行解决方案:

完整SQL代码

-- 创建测试临时表(与你的示例一致)
CREATE TABLE #temped (originalstring VARCHAR(100));
INSERT INTO #temped SELECT 'SUM([S720]) - SUM([S719]) * 2 + SUM([S719])';
INSERT INTO #temped SELECT 'SUM([R382]) + SUM([R989])';
INSERT INTO #temped SELECT 'SUM([S716]) * .295';

-- 递归CTE拆分每个表达式的独立项
WITH SplitExpressions AS (
    -- 初始化:给所有表达式开头统一加+,确保每个项都有明确符号
    SELECT 
        originalstring,
        CAST('+' + originalstring AS VARCHAR(MAX)) AS modifiedstring,
        1 AS itemindex
    FROM #temped
    UNION ALL
    -- 递归拆分每个+/-分隔的项
    SELECT 
        originalstring,
        STUFF(modifiedstring, 1, CHARINDEX(CASE WHEN CHARINDEX('+', modifiedstring, 2) > 0 THEN '+' ELSE '-' END, modifiedstring, 2), '') AS modifiedstring,
        itemindex + 1 AS itemindex
    FROM SplitExpressions
    WHERE CHARINDEX('+', modifiedstring, 2) > 0 OR CHARINDEX('-', modifiedstring, 2) > 0
),
-- 提取每个项的符号和核心内容
ExtractedItems AS (
    SELECT 
        originalstring,
        itemindex,
        SUBSTRING(modifiedstring, 1, 1) AS sign, -- 提取+/-符号
        LTRIM(SUBSTRING(modifiedstring, 2, CHARINDEX(CASE WHEN CHARINDEX('+', modifiedstring, 2) > 0 THEN '+' ELSE '-' END, modifiedstring, 2) - 2)) AS itemcontent
    FROM SplitExpressions
    WHERE CHARINDEX('+', modifiedstring, 2) > 0 OR CHARINDEX('-', modifiedstring, 2) = 0
    UNION ALL
    -- 处理最后一个没有后续分隔符的项
    SELECT 
        originalstring,
        itemindex,
        SUBSTRING(modifiedstring, 1, 1) AS sign,
        LTRIM(SUBSTRING(modifiedstring, 2, LEN(modifiedstring) - 1)) AS itemcontent
    FROM SplitExpressions
    WHERE CHARINDEX('+', modifiedstring, 2) = 0 AND CHARINDEX('-', modifiedstring, 2) = 0
),
-- 拆分每个项的SUM表达式和乘数,同时提取字段名
SplitItemParts AS (
    SELECT 
        originalstring,
        itemindex,
        sign,
        -- 分离SUM部分
        CASE WHEN CHARINDEX('*', itemcontent) > 0 THEN LTRIM(SUBSTRING(itemcontent, 1, CHARINDEX('*', itemcontent) - 1)) ELSE itemcontent END AS sum_expression,
        -- 分离乘数,无乘数则默认1
        CASE WHEN CHARINDEX('*', itemcontent) > 0 THEN LTRIM(SUBSTRING(itemcontent, CHARINDEX('*', itemcontent) + 1, LEN(itemcontent))) ELSE '1' END AS multiplier,
        -- 从SUM([XXX])中提取字段名XXX
        SUBSTRING(itemcontent, CHARINDEX('[', itemcontent) + 1, CHARINDEX(']', itemcontent) - CHARINDEX('[', itemcontent) - 1) AS field_name
    FROM ExtractedItems
)
-- 最终输出:按符号分配到正负列,带出乘数和字段名
SELECT 
    originalstring,
    CASE WHEN sign = '+' THEN sum_expression ELSE NULL END AS Col_positive,
    CASE WHEN sign = '-' THEN sum_expression ELSE NULL END AS Col_Neg,
    multiplier AS Multiplier,
    field_name AS FieldName
FROM SplitItemParts
ORDER BY originalstring, itemindex;

-- 清理临时表
DROP TABLE #temped;

代码说明

  1. 统一表达式格式:给每个表达式开头添加+,确保所有项都有明确的正负符号,避免第一个项无符号的处理麻烦。
  2. 递归拆分项:通过递归CTE把每个长表达式拆分成带符号的独立项,比如把SUM([S720]) - SUM([S719]) * 2 + SUM([S719])拆分为+SUM([S720])、-SUM([S719]) * 2、+SUM([S719])三个项。
  3. 拆分SUM与乘数:对每个项检查是否包含*,分离出SUM表达式和乘数,没有乘数的项默认乘数为1。
  4. 提取字段名:利用CHARINDEX定位[和]的位置,提取出中间的字段名称(如S720、R382)。
  5. 整理输出:根据项的符号,把SUM表达式放到对应的Col_positive或Col_Neg列,同时展示乘数和字段名。

测试结果示例

以你提供的第一条表达式为例,输出结果如下:

originalstringCol_positiveCol_NegMultiplierFieldName
SUM([S720]) - SUM([S719]) * 2 + SUM([S719])SUM([S720])NULL1S720
SUM([S720]) - SUM([S719]) * 2 + SUM([S719])NULLSUM([S719])2S719
SUM([S720]) - SUM([S719]) * 2 + SUM([S719])SUM([S719])NULL1S719

这个结果完全符合你的需求:正值项放入Col_positive,负值项放入Col_Neg,每个项的乘数对应显示,同时提取出了对应的字段名。

内容的提问来源于stack exchange,提问作者user2772056

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:57:15