Как извлечь только данные перед строкой шаблона

Как извлечь только строку после CX_EduDegree=??????? и заменить %20 пробелами. Данные разделены пробелами и никогда не находятся в одной и той же позиции.

Я попытался использовать патиндекс с подстрокой и заменить. Но я не добился успеха.

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 

person Lee    schedule 09.05.2016    source источник
comment
вы используете sql-сервер?   -  person Vamsi Prabhala    schedule 10.05.2016
comment
CX_EduDegree=.. всегда будет в конце строки?   -  person Vamsi Prabhala    schedule 10.05.2016
comment
Я использую sql-сервер. Нет, строка CX_EduDegree= никогда не бывает в одном и том же месте и может быть в начале, середине или конце. Он хранит данные от входа пользователя, и если они что-то не вводят, он падает раньше или позже, а иногда даже не включается.   -  person Lee    schedule 10.05.2016


Ответы (4)


Используйте комбинацию charindex, reverse и substring. Это будет работать, если CX_EduDegree= всегда появляется ближе к концу строки.

Демонстрация с примерами данных

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') 
person Vamsi Prabhala    schedule 09.05.2016
comment
когда я запускаю этот фрагмент кода, столбец extfield пуст для всего - person Lee; 10.05.2016
comment
как уже упоминалось, это будет работать только в том случае, если CX_EduDegree= всегда стоит в конце. - person Vamsi Prabhala; 10.05.2016

Используйте эту конструкцию:

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

Некоторые комментарии внутри кода для лучшего понимания. Как видите, 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)

Считаете ли вы это решение приемлемым?

person Alex Kudryashev    schedule 09.05.2016
comment
Это действительно близко к тому, что мне нужно. Я все еще получаю некоторые результаты, хотя после информации, которую я хочу, у меня есть больше .... 1352611 BS в сестринском деле CX_SupervisorPhone = 970-495-8100 - person Lee; 10.05.2016
comment
Части данных, которые появляются после и которые я хочу удалить, всегда будут начинаться с CX_[A-Z] - person Lee; 10.05.2016
comment
Посмотрите на мой код. Я специально занимался этим вопросом. PATINDEX('%CX_EduDegree=%',extFields)) - PATINDEX('%CX_EduDegree=%',extFields) - 13) как `длина подстроки. Результаты реальны из запроса. - person Alex Kudryashev; 10.05.2016
comment
1339940 BS в сестринском сестре 1352557 MS/MA в сестринском сестре 1352566 MS/MA в сестринском деле 1352579 Диплом 1352582 BS в сестринском сестре 1352590 Диплом 1352594 BS в сестринском деле 1352596 BS в сестринском положении 1352603 гг. 495-8100 1352618 г. н.э. в сестринском сестре 1352627 г. н.э. в сестринском сестре 1352630 BS/BA Другое поле 1352631 BS в сестринском сестре 1352638 BS в сестринском деле 1352640 г. н.э. MS / MA в области сестринского дела 1352677 MS / MA в области сестринского дела - person Lee; 10.05.2016
comment
Результаты получены из запроса, который я только что выполнил. он оставляет конечную информацию только тогда, когда есть что-то похожее на пробел и другая запись с CX_Supervisor или CX_VOL, или следующее сохраняемое поле... - person Lee; 10.05.2016
comment
Я думаю, я могу сделать еще один проход в обновлении для тех ??? обновить те, которые работают, и исправить остальные? - person Lee; 10.05.2016
comment
Большое спасибо за вашу помощь, Алекс, я определенно намного ближе, чем был. - person Lee; 10.05.2016

Один из способов сделать это с использованием типа данных 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 довольно медленный по сравнению с запросами на манипуляции со строками.

вы также можете использовать разделитель строк, подобный одному из ЗДЕСЬ

вот пример использования функции 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') 

все еще не так быстро, как некоторые другие здесь, но может быть легче понять или упростить вам доступ к другим полям.

person JamieD77    schedule 10.05.2016
comment
не удалось запустить первый блок кода в MS SQL Server... Сообщение 195, уровень 15, состояние 10, строка 5 "CONCAT" не является распознанным именем встроенной функции. - person Lee; 10.05.2016
comment
@ Ли, о да .. это материал sql 2012 .. я просто заменю на + - person JamieD77; 10.05.2016

Манипуляции со строками немного громоздки в 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 не гарантирует, что where будет обработан до outer apply подзапросов. На практике я думаю, что да, поэтому фильтрация выполняется, гарантируя, что подстрока находится в ExtFields. Если нет, это можно легко исправить с помощью case, но это немного усложняет ответ.

person Gordon Linoff    schedule 09.05.2016
comment
получил ошибки, используя этот код на сервере sql... Msg 174, уровень 15, состояние 1, строка 3. Для функции stuff требуется 4 аргумента (аргументов). Сообщение 102, уровень 15, состояние 1, строка 6 Неверный синтаксис рядом с «x2». - person Lee; 10.05.2016