SQL函数解析列中的文本
我有一个表,其中有一些文本我想解析出来,我非常接近解决方案,但它并不完全在那里。我有一个名为indicatornumerator的列,我想解析出与下面类似的内容,即我想将方括号之间的每个值放到新行上。从下面的输出可以看出,我得到了负号后第一个值的重复。这不会发生在那些没有负号的人身上 我的职能如下:SQL函数解析列中的文本,sql,sql-server,function,tsql,Sql,Sql Server,Function,Tsql,我有一个表,其中有一些文本我想解析出来,我非常接近解决方案,但它并不完全在那里。我有一个名为indicatornumerator的列,我想解析出与下面类似的内容,即我想将方括号之间的每个值放到新行上。从下面的输出可以看出,我得到了负号后第一个值的重复。这不会发生在那些没有负号的人身上 我的职能如下: alter function fn_breakdown (@string varchar(max)) returns @breakdown table ( originalstr varch
alter function fn_breakdown (@string varchar(max))
returns @breakdown table
(
originalstr varchar(max),
breakdownstr varchar(max)
)
as
begin
while charindex('r',@string,1) >0
begin
insert into @breakdown
select @string,
SUBSTRING(@string,CHARINDEX('r',@string,1),CHARINDEX(']',@string,1)-CHARINDEX('r',@string,1))
set @string = right(@string,len(@string)-CHARINDEX(')',@string,1))
end
return
end
我想做的第二件事是将负数之后的值作为负值返回,而不是-R101,因为我需要稍后减去这些值
非常感谢您的帮助
下面应该创建一个临时表,并向您显示我得到的输出。您将看到其中一行重复。我希望在indicatornumerator列中每个以“R”开头的值都有一行
创建表temped2
指示剂计量器varcharmax
插入temped2
选择'SUM[R4]+SUM[R1010]-SUM[R1035]+SUM[R1034]'
从temped2中选择*
交叉应用fn_故障指示器计数器下载一份,然后:
-- sample data
DECLARE @yourtable TABLE (IndicatorNumerator varchar(1000));
INSERT @yourtable
SELECT 'SUM([R4]) + SUM([R1010]) - SUM([R50]) + SUM([R200])' UNION ALL
SELECT 'SUM([R554]) + SUM([R210]) - SUM([R500]) + SUM([R999])';
-- Solution
SELECT
t.IndicatorNumerator,
breakdownstr = substring(t.IndicatorNumerator, ng.position+1, n.d-ng.position-1)
FROM @yourtable t
CROSS APPLY dbo.ngrams8k(t.IndicatorNumerator, 2) ng
CROSS APPLY (VALUES (charindex(']',t.IndicatorNumerator, ng.position+1))) n(d)
WHERE ng.token = '[R';
返回:
IndicatorNumerator breakdownstr
-------------------------------------------------------- --------------
SUM([R4]) + SUM([R1010]) - SUM([R50]) + SUM([R200]) R4
SUM([R4]) + SUM([R1010]) - SUM([R50]) + SUM([R200]) R1010
SUM([R4]) + SUM([R1010]) - SUM([R50]) + SUM([R200]) R50
SUM([R4]) + SUM([R1010]) - SUM([R50]) + SUM([R200]) R200
SUM([R554]) + SUM([R210]) - SUM([R500]) + SUM([R999]) R554
SUM([R554]) + SUM([R210]) - SUM([R500]) + SUM([R999]) R210
SUM([R554]) + SUM([R210]) - SUM([R500]) + SUM([R999]) R500
SUM([R554]) + SUM([R210]) - SUM([R500]) + SUM([R999]) R999
如果您使用的是SQL Server 2016和avove,请尝试此代码
;WITH cte_date
AS
(
SELECT indicatornumerator, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(indicatornumerator,'(',''),')',''),'[',''),']',''),'SUM',''),'- ','-') ParsedData
FROM #temped2
)
SELECT *
FROM cte_date
CROSS APPLY STRING_SPLIT(ParsedData, ' ')
WHERE [VALUE] != '+';
以下脚本将在sql server 2016之前运行
CREATE FUNCTION [dbo].[StrParse]
(@delimiter CHAR(1),
@csv NTEXT)
RETURNS @tbl TABLE(Keys NVARCHAR(255))
AS
BEGIN
DECLARE @len INT
SET @len = Datalength(@csv)
IF NOT @len > 0
RETURN
DECLARE @l INT
DECLARE @m INT
SET @l = 0
SET @m = 0
DECLARE @s VARCHAR(255)
DECLARE @slen INT
WHILE @l <= @len
BEGIN
SET @l = @m + 1--current position
SET @m = Charindex(@delimiter,Substring(@csv,@l + 1,255))
IF @m <> 0
SET @m = @m + @l
--insert @tbl(keys) values(@m)
SELECT @slen = CASE
WHEN @m = 0 THEN 255
ELSE @m - @l
END
IF @slen > 0
BEGIN
SET @s = Substring(@csv,@l,@slen)
INSERT INTO @tbl
(Keys)
SELECT @s
END
SELECT @l = CASE
WHEN @m = 0 THEN @len + 1
ELSE @m + 1
END
END
RETURN
END
GO
;WITH cte_date
AS
(
SELECT indicatornumerator, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(indicatornumerator,'(',''),')',''),'[',''),']',''),'SUM',''),'- ','-'),'+ ','') ParsedData
FROM #temped2
)
SELECT *
FROM cte_date
CROSS APPLY dbo.StrParse(' ', ParsedData)
go
请给出预期输出的示例。请指定您的RDBMS示例输出在屏幕截图中。左边是原始字符串,右边是所需的输出。我希望将原始字符串解析到单独的行上,但正如您在屏幕截图中看到的,有些字符串正在复制。此外,我正在使用SQL server 2017请勿发布屏幕截图。发布DML。对于第一个问题,请尝试将集合中的替换为']'。对于第二个问题,您可能需要搜索算术表达式的解析并从中获取原子。因为这就是你在这里要做的。但是请注意,括号是不平衡的。我认为IndicatorNumerator的开头缺少一个。只有在OP使用SQL 2016+的情况下,这才有效。OPs在发布时使用的SQL版本是一个很好的参数