Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL函数解析列中的文本_Sql_Sql Server_Function_Tsql - Fatal编程技术网

SQL函数解析列中的文本

SQL函数解析列中的文本,sql,sql-server,function,tsql,Sql,Sql Server,Function,Tsql,我有一个表,其中有一些文本我想解析出来,我非常接近解决方案,但它并不完全在那里。我有一个名为indicatornumerator的列,我想解析出与下面类似的内容,即我想将方括号之间的每个值放到新行上。从下面的输出可以看出,我得到了负号后第一个值的重复。这不会发生在那些没有负号的人身上 我的职能如下: alter function fn_breakdown (@string varchar(max)) returns @breakdown table ( originalstr varch

我有一个表,其中有一些文本我想解析出来,我非常接近解决方案,但它并不完全在那里。我有一个名为indicatornumerator的列,我想解析出与下面类似的内容,即我想将方括号之间的每个值放到新行上。从下面的输出可以看出,我得到了负号后第一个值的重复。这不会发生在那些没有负号的人身上

我的职能如下:

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版本是一个很好的参数