2017-10-11 10 views
2

Je veux déversée data colonne dans 3 nouvelles colonnesSQL chaîne Déversement par Virgule et espaces

  1. dernières
  2. premier
  3. poste

données ont des valeurs avec des espaces ou '' Comma Se-prated.

data 
ABC, RICK SEAN, MD 
MES, AEL B, MD FACC 
DAN, RK, MD 
OHI, NIK, MD F 
KA E SYME, PA-C 
ALL MUD, SIM, MD 
RINE EEMAN, FNP-C 
ABC, PQR DIR 

sortie requise:

desc      last  first  post 

ABC, RICK SEAN, MD   ABC   RICK SEAN MD   
MES, AEL B, MD FACC   MES   AEL B  MD FACC 
DAN, RK, MD     DAN   RK   MD 
OHI, NIK, MD F    OHI   NIK   MD F 
KA E SYME, PA-C    KA   E SYME  PA-C 
ALL MUD, SIM, MD   ALL MUD  SIM   MD 
RINE EEMAN, FNP-C   RINE  EEMAN  FNP-C 
ABC, PQR DIR    ABC   PQR   DIR 

vérifier la première colonne de données de rangée ont deux virgules et dernière rangée ont seulement une virgule.

échantillon créé ici http://rextester.com/BEHUP42399

select left(data, charindex(',', data) -1) from TTT 

Il a essayé de 'dernier' Nom de la colonne, mais donnant tort o/p pour savoir record virgule 'KA E SYME'. si les données ont une seule virgule et avant la virgule, il n'y a qu'un mot signifie qu'après la virgule il y a deux mots, alors le résultat sera. Vérifier le dernier enregistrement ABVC.

eg. ABC, PQR DIR     
+0

comment quelqu'un peut-il savoir que E SYME et TOUS MUD ne doivent pas être séparés? Quelle est la raison derrière cela? –

+0

Cette réponse peut vous aider: https://stackoverflow.com/a/46595896/2225030 –

+0

Vous feriez mieux de le faire dans votre code d'application. SQL n'est pas le bon outil pour ce travail – GurV

Répondre

2

Vous pouvez l'essayer en utilisant CROSS APLLY:

SELECT N.DATA [descr], 
     CASE 
      WHEN N.last = '' 
      THEN LTRIM(N.first) 
      ELSE LTRIM(N.last) 
     END last, 
     CASE 
      WHEN N.last = '' 
      THEN SUBSTRING(LTRIM(N.post), 1, CHARINDEX(CHAR(32), LTRIM(N.post))) 
      ELSE LTRIM(N.first) 
     END first, 
     CASE 
      WHEN N.last = '' 
      THEN SUBSTRING(LTRIM(N.post), (CHARINDEX(' ', LTRIM(N.post))+1), LEN(LTRIM(N.post))) 
      ELSE LTRIM(N.post) 
     END post 
FROM 
(
    SELECT D.DATA, 
      CASE 
       WHEN D.post IS NULL 
       THEN LEFT(D.last, CHARINDEX(' ', D.last)) 
       ELSE D.last 
      END last, 
      CASE 
       WHEN d.post IS NULL 
       THEN SUBSTRING(D.last, (CHARINDEX(' ', D.last)+1), LEN(D.last)) 
       ELSE d.first 
      END first, 
      CASE 
       WHEN D.post IS NULL 
       THEN d.first 
       ELSE d.post 
      END post 
    FROM 
    (
     SELECT DISTINCT 
       DATA, 
       Split.a.value('/M[1]', 'NVARCHAR(MAX)') last, 
       Split.a.value('/M[2]', 'NVARCHAR(MAX)') first, 
       Split.a.value('/M[3]', 'NVARCHAR(MAX)') post 
     FROM 
     (
      SELECT DATA, 
        CAST('<M>'+REPLACE(DATA, ',', '</M><M>')+'</M>' AS XML) AS String 
      FROM #TM 
     ) A 
     CROSS APPLY String.nodes('/M') Split(a) 
    ) D 
) N; 

Résultat souhaité:

desc      last  first  post 

ABC, RICK SEAN, MD   ABC   RICK SEAN MD   
MES, AEL B, MD FACC   MES   AEL B  MD FACC 
DAN, RK, MD     DAN   RK   MD 
OHI, NIK, MD F    OHI   NIK   MD F 
KA E SYME, PA-C    KA   E SYME  PA-C 
ALL MUD, SIM, MD   ALL MUD  SIM   MD 
RINE EEMAN, FNP-C   RINE  EEMAN  FNP-C 
ABC, PQR DIR    ABC   PQR   DIR 

Note: Le résultat ci-dessus selon les données fournies.

+0

Son travail pour 2 virgules serapted chaîne. Que pour une virgule simple. RINE EEMAN, FNP-C –

+0

ITs Fonctionne mais j'ai une autre condition. Nouvelle condition ajoutée dans les données Sampel. –

+0

@rohitpatil vérifier mis à jour. –

1

vous pouvez essayer une requête comme ci-dessous

Logic est que l'on trouve le nombre de virgules et d'ajouter des virgules pour les premiers espaces qui se produisent lorsque des virgules sont moins de 3 Cela fonctionne aussi quand il n'y a pas des virgules du tout dans la chaîne .

create table staging_tbl_single_row (data varchar(max)) 
insert into staging_tbl_single_row values 
('ABC, RICK SEAN, MD') 
,('MES, AEL B, MD FACC') 
,('DAN, RK, MD') 
,('OHI, NIK, MD F') 
,('KA E SYME, PA-C') 
,('ALL MUD, SIM, MD') 
,('RINE EEMAN, FNP-C'), 
('ABC, PQR DIR'); 

; with cte as 
(
select 
    row_number() over (order by (select NULL)) as column1, 
    column2= 
    case 
     when 
      (len(data)-len(replace(data,',',''))=2) 
     then 
      data 
     when 
      (len(data)-len(replace(data,',',''))=1) 
     then 
      case --check if space is to the left of comma 
        when 
         charindex(' ',left(data, charindex(',',data)))<>0 
        then 
         stuff(data,charindex(' ',data),1,',') 
        else 
         left(data, charindex(',',data))+ 
         stuff(
          substring(data, 
             charindex(',',data)+1, 
             len(data) 
            ), 
          charindex(' ', 
             substring(
              data, 
              charindex(',',data)+1, 
              len(data) 
             ), 
             2) 
          ,1,',') 
        end 

     when 
      (len(data)-len(replace(data,',',''))=0) 
     then 
       stuff(
     stuff(data,charindex(' ',data),1,',') 
     ,charindex(' ',stuff(data,charindex(' ',data),1,',')) 
     ,1,',') 

    end,data 
    from 
    staging_tbl_single_row 
) 

select 
    last=[1],first=[2],post=[3] 
from 
(
    select 
     t.column1, 
     split_values=SUBSTRING(t.column2, t1.N, ISNULL(NULLIF(CHARINDEX(',',t.column2,t1.N),0)-t1.N,8000)), 
     r= row_number() over(partition by column1 order by t1.N) 
    from cte t 
     join 
     (
      select 
       t.column2, 
       1 as N 
      from cte t 
       UNION ALL 
      select 
       t.column2, 
       t1.N + 1 as N 
      from cte t 
       join 
       (
       select 
        top 8000 
         row_number() over(order by (select NULL)) as N 
       from 
        sys.objects s1 
         cross join 
        sys.objects s2 
       ) t1 
      on SUBSTRING(t.column2,t1.N,1) = ',' 
     ) t1 
      on t1.column2=t.column2 
)a 
pivot 
( 
    max(split_values) for r in ([1],[2],[3]) 
    )p 

see working demo

+0

pouvez-vous vérifier cette condition 'ABC, PQR DIR'. sry j'ai oublié de mentionner –

+0

Son travail mais pour 1 million de dossiers cela prend beaucoup de temps. +1 –

0
;WITH Split_Names (data, xmlname) 
AS 
(
    SELECT data, 

    CONVERT(XML,'<Names><name>' 
    + REPLACE(data,',', '</name><name>') + '</name></Names>') AS xmlname 
     FROM TTT 
) 

SELECT CASE 
      WHEN s.post IS NULL 
      THEN LEFT(s.last, CHARINDEX(' ', s.last)-1) 
      ELSE s.last 
     END last, 
     CASE 
      WHEN s.post IS NULL 
      THEN SUBSTRING(s.last, (CHARINDEX(' ', s.last)+1), LEN(s.last)) 
      ELSE s.first 
     END first, 
     CASE 
      WHEN s.post IS NULL 
      THEN s.first 
      ELSE s.post 
     END Post FROM 
(
SELECT data,  
xmlname.value('/Names[1]/name[1]','varchar(MAX)') AS Last,  
xmlname.value('/Names[1]/name[2]','varchar(MAX)') AS First, 
xmlname.value('/Names[1]/name[3]','varchar(MAX)') AS Post 
FROM Split_Names 
)s 
+0

pouvez-vous vérifier cette condition 'ABC, PQR DIR'. sry j'ai oublié de mentionner –