【问题标题】:Split Values on AlphaNumeric Change into Multiple Rows将 AlphaNumeric 更改的值拆分为多行
【发布时间】:2017-12-11 21:27:38
【问题描述】:

我有来自存储过程的以下输出,我正在尝试拆分 Valueasstring 在数字和 alpha 之间切换到它自己的行并更新几个值:

Acct    Valuetypename   Valueasstring   EffectiveDate
123     Accepted        150ABC          8/15/2017
234     Accepted        500DF           10/17/2017
345     Accepted        1000ABC         10/17/2017
456     Accepted        25PV            10/3/2017
567     Accepted        100PV           8/15/2017

我试图用一个集合字符来分割,比如使用 XML 的逗号,但我一直坚持如何在类型更改时做到这一点。我不打算使用 XML。

Select a.Acct, a.Valuetypename, b.Valueasstring as ValueAsString, a.EffectiveDate
FROM
(
    SELECT *,
    CAST('<X>'+replace(T.Valueasstring,',','</X><X>')+'</X>' as XML) as my_Xml 
    FROM MyTable T
) a
CROSS APPLY
(
    SELECT my_Data.D.value('.','varchar(50)') as Valueasstring
    FROM a.my_Xml.nodes('X') as my_Data(D)
) b

我想要实现的,多行,valuetypename 更改为 alpha 值,Valueasstring 更改为 1(是)。

Acct    Valuetypename   Valueasstring   EffectiveDate
123     ABC             1               8/15/2017
123     Accepted        150             8/15/2017
234     DF              1               10/17/2017
234     Accepted        500             10/17/2017
345     ABC             1               10/17/2017
345     Accepted        1000            10/17/2017
456     PV              1               10/3/2017
456     Accepted        25              10/3/2017
567     PV              1               8/15/2017
567     Accepted        100             8/15/2017

我只能在我的代码中找到如何分隔一组字符,即逗号。但就我而言,我没有固定字符,甚至没有空格,只是从 Alpha 切换到 Numeric,反之亦然。

【问题讨论】:

    标签: sql sql-server xml tsql


    【解决方案1】:

    首先,您可以使用stuff() 函数将它们分隔为逗号,..(i.e. 150, ABC)。

    select 
           a.Acct,
           case when ISNUMERIC(m.value('.', 'varchar(max)')) <> 1 then m.value('.', 'varchar(max)') else a.Valuetypename end [Valuetypename],
           case when ISNUMERIC(m.value('.', 'varchar(max)')) <> 1 then '1' else m.value('.', 'varchar(max)') end [Valueasstring],
           a.EffectiveDate from
    (
        SELECT *, CAST('<m>'+replace(STUFF(Valueasstring,PATINDEX('%[A-Z]%', Valueasstring),0,','),',','</m><m>')+'</m>' as XML) as my_Xml  FROM  MyTable 
    )a cross apply my_Xml .nodes('/m') as Valueasstring(m)
    

    并且,借助简单的case 表达式,通过isnumeric() 函数检查数值

    结果:

    Acct    Valuetypename   Valueasstring   EffectiveDate
    123     ABC             1               8/15/2017
    123     Accepted        150             8/15/2017
    234     DF              1               10/17/2017
    234     Accepted        500             10/17/2017
    345     ABC             1               10/17/2017
    345     Accepted        1000            10/17/2017
    456     PV              1               10/3/2017
    456     Accepted        25              10/3/2017
    567     PV              1               8/15/2017
    567     Accepted        100             8/15/2017
    

    【讨论】:

    • 这很好,正是我需要的,谢谢!第一次使用 STUFF 功能。
    • 谢谢你,第一次来,并没有意识到接受是复选标记。完成!
    【解决方案2】:

    您不能使用没有分隔符的拆分,但您可以使用PATINDEX 查找模式的第一次出现:

    SET DATEFORMAT mdy;
    DECLARE @mockupTable TABLE(Acct INT,Valuetypename VARCHAR(100),Valueasstring VARCHAR(100),EffectiveDate DATE);
    INSERT INTO @mockupTable VALUES
     (123,'Accepted','150ABC','8/15/2017')
    ,(234,'Accepted','500DF','10/17/2017')
    ,(345,'Accepted','1000ABC','10/17/2017')
    ,(456,'Accepted','25PV','10/3/2017')
    ,(567,'Accepted','100PV','8/15/2017');
    

    查询使用CROSS APPLY 获取位置值作为命名变量。可以将PATINDEX 两次放入查询中,但这更好阅读:

    SELECT m.Acct
          ,m.Valuetypename
          ,LEFT(Valueasstring,FirstAlpha.Position-1) AS Numpart
          ,SUBSTRING(Valueasstring,FirstAlpha.Position,4000) AS Restpart
          ,m.EffectiveDate
    FROM @mockupTable AS m
    CROSS APPLY (SELECT PATINDEX('%[a-zA-Z]%',m.Valueasstring) AS Position) AS FirstAlpha
    

    结果

    Acct              Numpart   Restpart    EffectiveDate
    123     Accepted    150     ABC         2017-08-15
    234     Accepted    500     DF          2017-10-17
    345     Accepted    1000    ABC         2017-10-17
    456     Accepted    25      PV          2017-10-03
    567     Accepted    100     PV          2017-08-15
    

    您可以使用简单的CAST (... AS INT) 将 Numpart 转换为数字。

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 2021-12-19
      • 2021-12-07
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多