SQL自定义函数fn_breakdown解析问题及负号需求求助
问题解决:拆分带符号的R值到新行并避免重复
我来帮你搞定这两个问题:一是减号后的R值重复显示,二是给减号后的R值添加负号方便后续运算。先拆解下原函数的问题,再给出修正后的方案。
原函数的核心问题
- 原始字符串丢失:你在
INSERT时用的是循环中被截断后的@string,而非最初的完整输入字符串,这会导致结果里的originalstr列显示不同的截断片段,看起来像是R值重复。 - 符号未识别:原函数没有判断每个R值前面的
+/-符号,没法给减号后的R值自动添加负号。 - 截断逻辑不准确:用
CHARINDEX(')',@string)来截断字符串,遇到嵌套括号或减号后的括号时,截断位置容易出错,可能导致重复处理某些R值。
修正后的自定义函数
这个函数会保留原始字符串,准确识别每个R值的符号,并正确拆分每个方括号内的内容:
ALTER FUNCTION fn_breakdown (@originalString VARCHAR(MAX)) RETURNS @breakdown TABLE ( originalstr VARCHAR(MAX), breakdownstr VARCHAR(MAX) ) AS BEGIN -- 保存原始输入字符串,避免循环中修改丢失 DECLARE @currentStr VARCHAR(MAX) = @originalString; DECLARE @startPos INT, @endPos INT, @symbolPos INT; DECLARE @symbol CHAR(1), @rValue VARCHAR(MAX); -- 循环查找所有[R开头的目标片段 WHILE CHARINDEX('[R', @currentStr, 1) > 0 BEGIN -- 定位R的起始位置(跳过前面的[) SET @startPos = CHARINDEX('[R', @currentStr, 1) + 1; -- 定位对应的]的位置 SET @endPos = CHARINDEX(']', @currentStr, @startPos); -- 提取R开头的数值部分 SET @rValue = SUBSTRING(@currentStr, @startPos, @endPos - @startPos); -- 查找当前R值前面最近的符号(+/-) SET @symbolPos = @startPos - 2; -- 从[的前一个字符开始往前找 SET @symbol = '+'; -- 默认正号,处理开头无符号的情况 WHILE @symbolPos > 0 BEGIN IF SUBSTRING(@currentStr, @symbolPos, 1) IN ('+', '-') BEGIN SET @symbol = SUBSTRING(@currentStr, @symbolPos, 1); BREAK; END SET @symbolPos = @symbolPos - 1; END -- 根据符号给R值添加正负号 IF @symbol = '-' BEGIN SET @rValue = '-' + @rValue; END -- 插入结果,originalstr始终用原始完整字符串 INSERT INTO @breakdown SELECT @originalString, @rValue; -- 更新当前处理的字符串,从当前]的下一个位置继续 SET @currentStr = RIGHT(@currentStr, LEN(@currentStr) - @endPos); END RETURN; END
测试验证
用你提供的临时表语句测试:
CREATE TABLE #temped2 ( indicatornumerator VARCHAR(MAX) ) INSERT INTO #temped2 SELECT '(SUM([R4]) + SUM([R1010])) - (SUM([R1035]) + SUM([R1034]))' SELECT * FROM #temped2 CROSS APPLY fn_breakdown(indicatornumerator)
预期输出
| originalstr | breakdownstr |
|---|---|
| (SUM([R4]) + SUM([R1010])) - (SUM([R1035]) + SUM([R1034])) | R4 |
| (SUM([R4]) + SUM([R1010])) - (SUM([R1035]) + SUM([R1034])) | R1010 |
| (SUM([R4]) + SUM([R1010])) - (SUM([R1035]) + SUM([R1034])) | -R1035 |
| (SUM([R4]) + SUM([R1010])) - (SUM([R1035]) + SUM([R1034])) | -R1034 |
这样就完美解决了你的两个需求:
- 所有行的
originalstr都是原始完整字符串,不会出现看起来重复的R值。 - 减号后的R值自动添加负号,直接就能用于后续减法运算。
内容的提问来源于stack exchange,提问作者user2772056
相关产品推荐
相关产品推荐

