【问题标题】:How do I extract only the data before a pattern string如何仅提取模式字符串之前的数据
【发布时间】:2016-05-09 22:47:47
【问题描述】:

如何仅提取CX_EduDegree=??????? 之后的字符串并将%20 替换为空格。数据之间用空格隔开,并且永远不会在同一个位置。

我尝试将 patindex 与子字符串一起使用并替换。但我没有成功。

select top 5 clientid, extFields
from tblSYS_Clients
where ExtFields like '%CX_Edu%'
and ClientID in ('1633496','1633692','1453977','1657410','1584563','1655341','1632686','1352611','1484271','1361354') 
clientid    extFields
1352611 CX_CurrentJobStartDate=01/20/2001  CX_CurrentJobHours=40  CX_SupervisorName=Rhonda%20Kaiser  CX_EduDegree=BS%20in%20Nursing  CX_SupervisorPhone=970-495-8100
1361354 CX_CurrentJobStartDate=06/20/1997  CX_CurrentJobHours=30  CX_SupervisorName=Georgia%20Chapin  CX_SupervisorPhone=702-616-5632  CX_EduDegree=MS/MA%20%20in%20Nursing
1453977 CX_CurrentJobStartDate=08/20/1990  CX_CurrentJobHours=40  CX_SupervisorName=Jan%20Rasco  CX_SupervisorPhone=281-631-8789  CX_EduDegree=Diploma
1484271 CX_CurrentJobStartDate=01/01/2011  CX_CurrentJobHours=40  CX_SupervisorName=Kay%20Hix  CX_SupervisorPhone=317-329-7209  CX_EduDegree=AD%20in%20Nursing
1584563 CX_CurrentJobStartDate=11/26/2006  CX_CurrentJobHours=40  CX_SupervisorName=PHILLIP%20MOISUK  CX_SupervisorPhone=916-453-4545  CX_EduDegree=BS%20in%20Nursing

我想看到的结果:

1633496 BS in Nursing 
1633692 BS in Nursing 
1453977 Diploma 
1657410 AD in Nursing 
1584563 BS in Nursing 
1655341 AD in Nursing 
1632686 BS in Nursing 
1352611 BS in Nursing 
1484271 AD in Nursing 
1361354 MS/MA in Nursing 

【问题讨论】:

  • 你用的是sql server吗?
  • CX_EduDegree=.. 会一直在字符串的末尾吗?
  • 我正在使用 sql server。不,字符串 CX_EduDegree= 永远不会在同一个地方,可能在开头、中间或结尾。它存储来自用户输入的数据,如果他们不输入内容,它会早晚落下,有时甚至不包括在内。

标签: sql sql-server patindex


【解决方案1】:

使用charindexreversesubstring 的组合。如果CX_EduDegree= 总是出现在字符串的末尾,这将起作用。

Demo with sample data

select clientid,
substring(
          extfields
          ,charindex('CX_EduDegree=',extFields)+len('CX_EduDegree=')
          ,charindex(' ',extFields)
         ) as extfield
from tblSYS_Clients
where ExtFields like '%CX_Edu%'
and ClientID in ('1633496','1633692','1453977','1657410','1584563','1655341','1632686','1352611','1484271','1361354') 

【讨论】:

  • 当我运行这段代码时,extfield 列对于所有内容都是空白的
  • 如前所述,这仅在 CX_EduDegree= 始终位于末尾时才有效。
【解决方案2】:

使用这个结构:

select clientid, replace(SUBSTRING(extFields,
   PATINDEX('%CX_EduDegree=%',extFields)+13,
      charindex(' ', extFields+' ',
          PATINDEX('%CX_EduDegree=%',extFields)) - 
             PATINDEX('%CX_EduDegree=%',extFields) - 13),'%20',' ') ex 
from  
(values 
(1352611, 'CX_CurrentJobStartDate=01/20/2001  CX_CurrentJobHours=40  CX_SupervisorName=Rhonda%20Kaiser  CX_EduDegree=BS%20in%20Nursing  CX_SupervisorPhone=970-495-8100'), 
(1361354, 'CX_CurrentJobStartDate=06/20/1997  CX_CurrentJobHours=30  CX_SupervisorName=Georgia%20Chapin  CX_SupervisorPhone=702-616-5632  CX_EduDegree=MS/MA%20%20in%20Nursing'), 
(1453977, 'CX_CurrentJobStartDate=08/20/1990  CX_CurrentJobHours=40  CX_SupervisorName=Jan%20Rasco  CX_SupervisorPhone=281-631-8789  CX_EduDegree=Diploma'), 
(1484271, 'CX_CurrentJobStartDate=01/01/2011  CX_CurrentJobHours=40  CX_SupervisorName=Kay%20Hix  CX_SupervisorPhone=317-329-7209  CX_EduDegree=AD%20in%20Nursing'), 
(1584563, 'CX_CurrentJobStartDate=11/26/2006  CX_CurrentJobHours=40  CX_SupervisorName=PHILLIP%20MOISUK  CX_SupervisorPhone=916-453-4545  CX_EduDegree=BS%20in%20Nursing') 
) t(clientid,    extFields)

结果:

clientid    ex
1352611 BS in Nursing
1361354 MS/MA  in Nursing
1453977 Diploma
1484271 AD in Nursing
1584563 BS in Nursing

代码中的一些 cmets 以便更好地理解。如您所见,charindex 也可以。结果是一样的。

select clientid, 
replace(
SUBSTRING(extFields,--string to work with
   charindex('CX_EduDegree=',extFields)+13, --start position; 13 is length of CX_EduDegree=
      charindex(' ', extFields+' ', --searching end position +' ' to make sure that space exists
          charindex('CX_EduDegree=',extFields) -- start searching ' ' after this position
          ) --end position found
             - charindex('CX_EduDegree=',extFields) - 13) -- calculate length
             ,'%20',' ') ex --final touch - remove ugly %20 
from  
(values 
(1352611, 'CX_CurrentJobStartDate=01/20/2001  CX_CurrentJobHours=40  CX_SupervisorName=Rhonda%20Kaiser  CX_EduDegree=BS%20in%20Nursing  CX_SupervisorPhone=970-495-8100'), 
(1361354, 'CX_CurrentJobStartDate=06/20/1997  CX_CurrentJobHours=30  CX_SupervisorName=Georgia%20Chapin  CX_SupervisorPhone=702-616-5632  CX_EduDegree=MS/MA%20%20in%20Nursing'), 
(1453977, 'CX_CurrentJobStartDate=08/20/1990  CX_CurrentJobHours=40  CX_SupervisorName=Jan%20Rasco  CX_SupervisorPhone=281-631-8789  CX_EduDegree=Diploma'), 
(1484271, 'CX_CurrentJobStartDate=01/01/2011  CX_CurrentJobHours=40  CX_SupervisorName=Kay%20Hix  CX_SupervisorPhone=317-329-7209  CX_EduDegree=AD%20in%20Nursing'), 
(1584563, 'CX_CurrentJobStartDate=11/26/2006  CX_CurrentJobHours=40  CX_SupervisorName=PHILLIP%20MOISUK  CX_SupervisorPhone=916-453-4545  CX_EduDegree=BS%20in%20Nursing') 
) t(clientid,    extFields)

你觉得这个解决方案可以接受吗?

【讨论】:

  • 这真的很接近我的需要。我仍然得到一些结果,尽管在我想要的信息之后还有更多结果...... 1352611 BS in Nursing CX_SupervisorPhone=970-495-8100
  • 之后出现的以及我想要剥离的数据部分将始终以 CX_[A-Z] 开头
  • 看看我的代码。我专门针对这个问题。 PATINDEX('%CX_EduDegree=%',extFields)) - PATINDEX('%CX_EduDegree=%',extFields) - 13) 作为`子串长度。查询的结果是真实的。
  • 1339940 护理学士学位 1352557 护理硕士学位/硕士学位 1352566 护理硕士学位/硕士学位 1352579 文凭 1352582 护理学士学位 1352590 文凭 1352594 护理学士学位 1352596 护理学士学位/护理硕士学位 135526006 AD1352603 1352611在护理中的护理1352630 BS / BA在护理1352630 BS中的护理中= 970-495-8100 1352627 BS / BA在护理1352647课程中的护理1352647 BS中的宣传中,在护理1352664 BS中护理学 1352672 护理学硕士/硕士 1352676 护理学硕士/硕士 1352677 护理学硕士/硕士
  • 结果来自我刚刚运行的查询。只有当有一个空格和另一个带有 CX_Supervisor 或 CX_VOL 的条目,或者正在存储的下一个字段时,它才会留下尾随信息...
【解决方案3】:

一种使用 XML 数据类型的方法

SELECT  clientid,
        REPLACE(t.cx.value('(r/@CX_EduDegree)[1]', 'varchar(100)'),'%20',' ') AS degree
FROM    (
    SELECT  clientid, 
            CAST('<r ' + REPLACE(REPLACE(extFields,'=','="') , '  ','"/><r ') + '"></r>') AS XML) cx
    FROM    tblSYS_Clients
    WHERE   clientid in ('1633496','1633692','1453977','1657410','1584563','1655341','1632686','1352611','1484271','1361354') 
) t

与字符串操作查询相比,xml 相当慢。

您可以做的另一件事是使用字符串拆分器,例如 HERE 之一

这是一个使用 Jeff Moden 的 DelimitedSplit8K 函数的示例。

SELECT  t1.clientid,
        REPLACE(t2.Item,'CX_EduDegree=','')
FROM    tblSYS_Clients t1
        CROSS APPLY (
            SELECT REPLACE(t.Item, '%20', ' ') Item 
            FROM dbo.DelimitedSplit8K(t1.extFields, '  ') t 
            WHERE t.Item LIKE 'CX_EduDegree%' 
        ) t2
WHERE   clientid in ('1633496','1633692','1453977','1657410','1584563','1655341','1632686','1352611','1484271','1361354') 

仍然不如这里的其他一些快,但可能更容易理解或让您更容易获得其他领域。

【讨论】:

  • 无法在 MS SQL Server 中运行第一个代码块... Msg 195, Level 15, State 10, Line 5 'CONCAT' 不是可识别的内置函数名称。跨度>
  • @Lee 哦是的.. 那是 sql 2012 的东西.. 只是替换为 +
【解决方案4】:

在 SQL Server 中字符串操作有点麻烦。我喜欢使用outer apply

select c.clientid, c.extFields, x2.x2
from tblSYS_Clients c outer apply
     (select stuff(c.ExtFields, 1, charindex('CX_edu', c.ExtFields), '') as x1
     ) x outer apply
     (select replace(left(x.x1, charindex(' ', x1)), '%20', ' ') as x2
     ) x2
where c.ExtFields like '%CX_Edu%' and
      c.ClientID in ('1633496', '1633692', '1453977', '1657410', '1584563', '1655341', '1632686', '1352611', '1484271', '1361354') ;

注意:我认为以上方法可行。 SQL Server 不保证在 outer apply 子查询之前处理 where。实际上,我认为确实如此,因此完成过滤以确保子字符串位于ExtFields 中。如果没有,可以使用case 轻松解决此问题,但这会使答案有点复杂。

【讨论】:

  • 在 sql server 上使用此代码收到错误... Msg 174, Level 15, State 1, Line 3 该 stuff 函数需要 4 个参数。消息 102,级别 15,状态 1,第 6 行 'x2' 附近的语法不正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多