【问题标题】:Trim a part of a String修剪字符串的一部分
【发布时间】:2018-05-15 10:02:11
【问题描述】:

我有一个表,其中有一列很长。我只需要从列中获取名称。

这是列名:

QSTY-IOM-HFVNBJGYG | Mobile #: 9876541323 | CUSTOMER NAME: MNOP UNIPOUYTREA POIUY | INVOICE DATE:02/28/18 | EMP#: 101466 | EMPLOYEE NAME: ANGELINA CASIANO

我只需要从该列中提取客户名称。我尝试了 Charindex,它显示了

的错误消息

传递给 LEFT 或 SUBSTRING 函数的长度参数无效。

输出:

MNOP UNIPOUYTREA POIUY

【问题讨论】:

  • "我试过 Charindex" 我们可以看看那个尝试吗?这可能是正确的方法。
  • 选择子串 (Description, charindex('|',Description,1)+1, charindex(' ',Description,1)-charindex('|',Description,1) ),* from #决赛

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

由于您使用的是 SQL Server 2016,因此您可以使用它内置的 STRING_SPLIT 方法将您的字符串转换为表格。 那么你所要做的就是从以CUSTOMER NAME:开头的表中选择值,像这样:

DECLARE @s varchar(300) = 'QSTY-IOM-HFVNBJGYG | Mobile #: 9876541323 | CUSTOMER NAME: MNOP UNIPOUYTREA POIUY | INVOICE DATE:02/28/18 | EMP#: 101466 | EMPLOYEE NAME: ANGELINA CASIANO'

SELECT [value]
FROM STRING_SPLIT(@s, '|')
WHERE LTRIM([value]) LIKE 'CUSTOMER NAME:%'

但是,如果可能,您应该阅读Is storing a delimited list in a database column really that bad? 并规范化您的数据库。

【讨论】:

    【解决方案2】:

    对于 SQL-Serer-2016+,您应该使用 STRING_SPLIT

    对于较低版本,我会使用这种方法:

    XQueryT-SQL 的直接组合

    DECLARE @string VARCHAR(1000)='QSTY-IOM-HFVNBJGYG | Mobile #: 9876541323 | CUSTOMER NAME: MNOP UNIPOUYTREA POIUY | INVOICE DATE:02/28/18 | EMP#: 101466 | EMPLOYEE NAME: ANGELINA CASIANO';
    
    WITH Casted AS
    (
        SELECT CAST('<x>' + REPLACE((SELECT @string AS [*] FOR XML PATH('')),' | ','</x><x>') + '</x>' AS XML)
              .query('/x[substring(text()[1],1,13)="CUSTOMER NAME"]')
              .value('(/x/text())[1]','varchar(1000)') AS TheFragment
    )
    SELECT LTRIM(RTRIM(SUBSTRING(TheFragment,CHARINDEX(':',TheFragment)+2,1000)))
    FROM Casted;
    

    CTE 会将您的字符串转换为 XML,从而允许单独读取每个部分。 .query() 将返回以"CUSTOMER NAME" 开头的一个片段,而.value() 会从该片段中取出(完整的)文本。剩下的就简单了SUBSTRING...

    【讨论】:

      【解决方案3】:

      如果格式一致,可以尝试如下:

      declare @val varchar(max) = 'QSTY-IOM-HFVNBJGYG | Mobile #: 9876541323 | CUSTOMER NAME: MNOP UNIPOUYTREA POIUY | INVOICE DATE:02/28/18 | EMP#: 101466 | EMPLOYEE NAME: ANGELINA CASIANO'
      
      select substring(@val, charindex('CUSTOMER NAME:', @val) + 15, charindex('INVOICE DATE:', @val) - (charindex('CUSTOMER NAME:', @val) + 18))
      

      【讨论】:

      • 这是错误:传递给 LEFT 或 SUBSTRING 函数的长度参数无效
      • 您的所有字符串是否与@val 变量中存储的字符串格式相同?
      • 不,它们会根据名称的长度不断变化
      • 这是可以理解的。但我的意思是字符串的整体结构是否有任何区别..
      • @Looking_for_answers 的意思是:“客户姓名”总是紧跟在“发票日期”之后,就像在这个示例中一样,或者片段可以按任何顺序排列吗?
      【解决方案4】:

      这是一种寻找CUSTOMER NAME的方法:

      with params as (
            select ' CUSTOMER NAME: ' as custname
           )
      select t.*,
             (case when t.col like '%' + custname + '%'
                   then s2.s2 
              end) as customer_name
      from params cross join
           t outer apply
           (select substring(t.col, charindex(custname, col + custname), len(col))as s1
           ) s1 outer apply
           (select stuff(left(s1.s1, charindex('|', s1.s1 + '|') - 2),
                         1, len(custname) + 1, ''
                        ) as s2
           ) s2;
      

      如果customer_name 位于字符串的末尾,无论值的顺序如何,即使'CUSTOMER NAME' 根本不在字符串中,这应该可以工作。

      当然,如果您使用的是 SQL Server 2016,那么使用 split_string() 的解决方案会更好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-07
        • 1970-01-01
        • 2018-01-13
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多